Android viewholder class 范围广
Android viewholder class wide scope
我有一个使用 viewholder 模式的列表适配器,我的问题是我需要在同一 class 中包含的 AsyncTask 的 onpostexecute() 中从 viewholder 更新 TextView,但这总是 returns TextView 上的空指针,如何从 viewholder 给我的 textviews 提供足够的范围,以便我可以在 AsyncTask 中更改它们?我将在下面包含一个代码示例,在此先感谢
public class ListAdapter extends BaseAdapter {
TextView tvA1, tvA2;
Integer submitId;
String submitQuestion;
public ListAdapter() {
....
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
friendsViewHolder holder = null;
if (convertView == null) {
holder = new friendsViewHolder();
convertView = inflater.inflate(R.layout.list_item_status, null);
holder.tvA1 = (TextView) convertView
.findViewById(R.id.tvA1);
holder.tvA2 = (TextView) convertView
.findViewById(R.id.tvA2);
holder.btQ1 = (LinearLayout) convertView
.findViewById(R.id.btConfirm);
holder.btQ2 = (LinearLayout) convertView
.findViewById(R.id.btDeny);
convertView.setTag(holder);
} else {
holder = (friendsViewHolder) convertView.getTag();
}
tvA1 = holder.tvA1;
tvA2 = holder.tvA2;
holder.btQ1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
submitId = id;
submitQuestion = q1;
new UpdateAnswer().execute();
}
});
holder.btQ2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
submitId = id;
submitQuestion = q2;
new UpdateAnswer().execute();
}
});
return convertView;
}
static class friendsViewHolder {
TextView tvA1, tvA2;
LinearLayout btQ1, btQ2;
}
private class UpdateAnswer extends AsyncTask<Void, Void, ArrayList<Object>> {
@Override
protected ArrayList<Object> doInBackground(Void... params) {
return apiHelper.submitAnswer(submitId, submitQuestion);
}
@Override
protected void onPostExecute(ArrayList<Object> answers) {
super.onPostExecute(answers);
if (answers != null) {
Integer a1 = (Integer) answers.get(1);
Integer a2 = (Integer) answers.get(2);
//Error here
tvA1.setText(a1);
tvA1.setVisibility(View.VISIBLE);
//error here
tvA2.setText(a2);
tvA2.setVisibility(View.VISIBLE);
}
}
}
}
Java 是按值传递,但您可以在值中发送对象的引用。我已经使用了上面的内容,并将 holder 的引用发送给了 AsyncTask。
public class ListAdapter extends BaseAdapter {
TextView tvA1, tvA2;
Integer submitId;
String submitQuestion;
public ListAdapter() {
....
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
friendsViewHolder holder = null;
if (convertView == null) {
holder = new friendsViewHolder();
convertView = inflater.inflate(R.layout.list_item_status, null);
holder.tvA1 = (TextView) convertView
.findViewById(R.id.tvA1);
holder.tvA2 = (TextView) convertView
.findViewById(R.id.tvA2);
holder.btQ1 = (LinearLayout) convertView
.findViewById(R.id.btConfirm);
holder.btQ2 = (LinearLayout) convertView
.findViewById(R.id.btDeny);
convertView.setTag(holder);
} else {
holder = (friendsViewHolder) convertView.getTag();
}
holder.btQ1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
submitId = id;
submitQuestion = q1;
new UpdateAnswer(holder).execute();
}
});
holder.btQ2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
submitId = id;
submitQuestion = q2;
new UpdateAnswer().execute();
}
});
return convertView;
}
static class friendsViewHolder {
TextView tvA1, tvA2;
LinearLayout btQ1, btQ2;
}
private class UpdateAnswer extends AsyncTask<Void, Void, ArrayList<Object>> {
friendsViewHolder holder;
UpdateAnswer(friendsViewHolder holder)
{
this.holder = holder;
}
@Override
protected ArrayList<Object> doInBackground(Void... params) {
return apiHelper.submitAnswer(submitId, submitQuestion);
}
@Override
protected void onPostExecute(ArrayList<Object> answers) {
super.onPostExecute(answers);
if (answers != null) {
Integer a1 = (Integer) answers.get(1);
Integer a2 = (Integer) answers.get(2);
//Error here
holder.tva1.setText(a1);
holder.tva1.setVisibility(View.VISIBLE);
//error here
holder.tva2.setText(a2);
holder.tva2.setVisibility(View.VISIBLE);
}
}
}
}
让我们在这里和那里改变一些东西:)
让我们交朋友ViewHolder public,我还需要在java中添加它以某种方式自定义命名类,名称以驼峰字母开头,只需将FirstLetterOfEeachWordIsBig :)
让我们将构造函数添加到更新任务:)
private class UpdateAnswer extends AsyncTask<Void, Void, ArrayList<Object>> {
int submitId;
String submitQuestion;
friendsViewHolder holder;
public UpdateAnswer (int submitId, String submitQuestion, friendsViewHolder holder) {
this.submitId = submitId;
this.submitQuestion = submitQuestion;
this.holder = holder;
}
点击让我们更改为
final frendsViewHolder finalHolder = holder;
holder.btQ1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new UpdateAnswer(id, q1, finalHolder).execute();
}
});
我们不再需要全局 TvA1、tvA2、submitId、submitQuestion;
最后我们需要编辑 onPostExecute,但是我认为这很难,因为您已经转发了 holder 值 :)
holder.tvA1.setText(a1);
holder.tvA1.setVisibility(View.VISIBLE);
holder.tvA2.setText(a2);
holder.tvA2.setVisibility(View.VISIBLE);
在 java 中,您可以创建构造函数以允许将其他数据传递给对象,我们使用它来为我们的任务设置 id、问题和持有人,并且为了将该信息传递给其他对象,我们不应该这样做使用全局值(每个进程都可以更改它们),考虑您的呼叫 "apiHelper.submitAnswer(submitId, submitQuestion)" 需要很长时间才能继续(例如半秒)的情况,然后用户在半秒内首先点击答案并回答c 关于第 3 个问题,通过全局传递值,您无法确定接受哪个答案:)
干杯:)
我有一个使用 viewholder 模式的列表适配器,我的问题是我需要在同一 class 中包含的 AsyncTask 的 onpostexecute() 中从 viewholder 更新 TextView,但这总是 returns TextView 上的空指针,如何从 viewholder 给我的 textviews 提供足够的范围,以便我可以在 AsyncTask 中更改它们?我将在下面包含一个代码示例,在此先感谢
public class ListAdapter extends BaseAdapter {
TextView tvA1, tvA2;
Integer submitId;
String submitQuestion;
public ListAdapter() {
....
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
friendsViewHolder holder = null;
if (convertView == null) {
holder = new friendsViewHolder();
convertView = inflater.inflate(R.layout.list_item_status, null);
holder.tvA1 = (TextView) convertView
.findViewById(R.id.tvA1);
holder.tvA2 = (TextView) convertView
.findViewById(R.id.tvA2);
holder.btQ1 = (LinearLayout) convertView
.findViewById(R.id.btConfirm);
holder.btQ2 = (LinearLayout) convertView
.findViewById(R.id.btDeny);
convertView.setTag(holder);
} else {
holder = (friendsViewHolder) convertView.getTag();
}
tvA1 = holder.tvA1;
tvA2 = holder.tvA2;
holder.btQ1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
submitId = id;
submitQuestion = q1;
new UpdateAnswer().execute();
}
});
holder.btQ2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
submitId = id;
submitQuestion = q2;
new UpdateAnswer().execute();
}
});
return convertView;
}
static class friendsViewHolder {
TextView tvA1, tvA2;
LinearLayout btQ1, btQ2;
}
private class UpdateAnswer extends AsyncTask<Void, Void, ArrayList<Object>> {
@Override
protected ArrayList<Object> doInBackground(Void... params) {
return apiHelper.submitAnswer(submitId, submitQuestion);
}
@Override
protected void onPostExecute(ArrayList<Object> answers) {
super.onPostExecute(answers);
if (answers != null) {
Integer a1 = (Integer) answers.get(1);
Integer a2 = (Integer) answers.get(2);
//Error here
tvA1.setText(a1);
tvA1.setVisibility(View.VISIBLE);
//error here
tvA2.setText(a2);
tvA2.setVisibility(View.VISIBLE);
}
}
}
}
Java 是按值传递,但您可以在值中发送对象的引用。我已经使用了上面的内容,并将 holder 的引用发送给了 AsyncTask。
public class ListAdapter extends BaseAdapter {
TextView tvA1, tvA2;
Integer submitId;
String submitQuestion;
public ListAdapter() {
....
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
friendsViewHolder holder = null;
if (convertView == null) {
holder = new friendsViewHolder();
convertView = inflater.inflate(R.layout.list_item_status, null);
holder.tvA1 = (TextView) convertView
.findViewById(R.id.tvA1);
holder.tvA2 = (TextView) convertView
.findViewById(R.id.tvA2);
holder.btQ1 = (LinearLayout) convertView
.findViewById(R.id.btConfirm);
holder.btQ2 = (LinearLayout) convertView
.findViewById(R.id.btDeny);
convertView.setTag(holder);
} else {
holder = (friendsViewHolder) convertView.getTag();
}
holder.btQ1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
submitId = id;
submitQuestion = q1;
new UpdateAnswer(holder).execute();
}
});
holder.btQ2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
submitId = id;
submitQuestion = q2;
new UpdateAnswer().execute();
}
});
return convertView;
}
static class friendsViewHolder {
TextView tvA1, tvA2;
LinearLayout btQ1, btQ2;
}
private class UpdateAnswer extends AsyncTask<Void, Void, ArrayList<Object>> {
friendsViewHolder holder;
UpdateAnswer(friendsViewHolder holder)
{
this.holder = holder;
}
@Override
protected ArrayList<Object> doInBackground(Void... params) {
return apiHelper.submitAnswer(submitId, submitQuestion);
}
@Override
protected void onPostExecute(ArrayList<Object> answers) {
super.onPostExecute(answers);
if (answers != null) {
Integer a1 = (Integer) answers.get(1);
Integer a2 = (Integer) answers.get(2);
//Error here
holder.tva1.setText(a1);
holder.tva1.setVisibility(View.VISIBLE);
//error here
holder.tva2.setText(a2);
holder.tva2.setVisibility(View.VISIBLE);
}
}
}
}
让我们在这里和那里改变一些东西:)
让我们交朋友ViewHolder public,我还需要在java中添加它以某种方式自定义命名类,名称以驼峰字母开头,只需将FirstLetterOfEeachWordIsBig :)
让我们将构造函数添加到更新任务:)
private class UpdateAnswer extends AsyncTask<Void, Void, ArrayList<Object>> {
int submitId;
String submitQuestion;
friendsViewHolder holder;
public UpdateAnswer (int submitId, String submitQuestion, friendsViewHolder holder) {
this.submitId = submitId;
this.submitQuestion = submitQuestion;
this.holder = holder;
}
点击让我们更改为
final frendsViewHolder finalHolder = holder;
holder.btQ1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new UpdateAnswer(id, q1, finalHolder).execute();
}
});
我们不再需要全局 TvA1、tvA2、submitId、submitQuestion;
最后我们需要编辑 onPostExecute,但是我认为这很难,因为您已经转发了 holder 值 :)
holder.tvA1.setText(a1);
holder.tvA1.setVisibility(View.VISIBLE);
holder.tvA2.setText(a2);
holder.tvA2.setVisibility(View.VISIBLE);
在 java 中,您可以创建构造函数以允许将其他数据传递给对象,我们使用它来为我们的任务设置 id、问题和持有人,并且为了将该信息传递给其他对象,我们不应该这样做使用全局值(每个进程都可以更改它们),考虑您的呼叫 "apiHelper.submitAnswer(submitId, submitQuestion)" 需要很长时间才能继续(例如半秒)的情况,然后用户在半秒内首先点击答案并回答c 关于第 3 个问题,通过全局传递值,您无法确定接受哪个答案:)
干杯:)