【问题标题】:Updating TextView from AsyncTask launched from the adapter (getView)从适配器启动的 AsyncTask 更新 TextView (getView)
【发布时间】:2013-10-30 11:31:01
【问题描述】:

我在从 AsynTask 更新 TextView 时遇到了一个奇怪的问题。 在我的适配器的 getView 函数中,我启动了一个 AsyncTask 以计算一个数字并将其显示在屏幕上。

问题是getView函数为单个项目调用了多次,因此计算了我要显示的数次,效率不高。

我经过调查发现,每当我尝试限制对 AsyncTask 的 os 调用次数时,屏幕上都不会显示该数字(没有错误消息或异常)

public View getView(int position, View convertView, ViewGroup parent) {
    LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View rowView = inflater.inflate(R.layout.category_item, null);
    TextView tvCategory = (TextView) rowView.findViewById(R.id.tvCategory);
    TextView tvUnreadNews = (TextView) rowView.findViewById(R.id.tvUnreadNews);

    Category cat = mCategoriesList.get(position);
    tvCategory.setText(cat.getName());
    if(!cat.isInitialized()) //<-- If I delete this line it works, but inefficienly, as the AsyncTask is launched many times repeatedly
    {
            cat.setIsInitialized(true)
        new GetNewsForCategoryTask(cat, tvUnreadNews, mContext).execute(cat.getId());
    }
    return rowView;
}

这是异步任务。重复调用时正确更新TextView,但类别仅调用一次时不更新值:

public class GetNewsForCategoryTask extends AsyncTask<String, Integer, JSONArray>{

private Context mContext;
private String mCategoryId;
private TextView mTvUnread;
private Category mCategory;

public GetNewsForCategoryTask(Category cat, TextView tvUnread, Context context) {
    mTvUnread = tvUnread;
    mCategory = cat;
    mContext = context;
}

@Override
protected JSONArray doInBackground(String... params) {
    mCategoryId = params[0];

     ...

}

@Override
protected void onProgressUpdate(Integer... values) {
    mTvUnread.setText(Integer.toString(values[0]));
}

@Override
protected void onPostExecute(JSONArray result) {
    if(result != null && mThrown == null)
    {
        publishProgress(mCategory.getUnreadNewsSet().size());
    }
}

}

有没有人可能是这种奇怪行为的原因?我检查了 AsyncTask 仅在启动它们一次 pro 类别时被正确调用,但只是不更新​​布局。为什么启动多次专业类别有效?

更新: 我一直在测试,看起来问题出在 getView() 函数上。如果我检查变量是否已初始化,那么只有 ListView 的第一个元素会发生变化……ListView 中其他项目的所有值都会发生变化!

所以看起来 TextView 试图设置的值始终是第一个(ListView 的第一个元素)。

有什么想法???

【问题讨论】:

  • 是mTvUnread异步任务的私有字段吗?
  • 是的,它是 AsyncTask 的私有字段。我在构造函数上初始化它。
  • 我在你的代码中看不到?你能发布完整的适配器和异步任务,以便我可以运行它..
  • mTvUnread 在你声明的地方。
  • 我编辑了代码,你可以看到现在声明的地方。

标签: android multithreading android-asynctask textview adapter


【解决方案1】:

看看这个:

Category cat = mCategoriesList.get(position);
tvCategory.setText(cat.getName());
if(!cat.isInitialized()) //<-- If I delete this line it works, but inefficienly, as the AsyncTask is launched many times repeatedly
{
    cat.setIsInitialized(true)
    new GetNewsForCategoryTask(cat, tvUnreadNews, mContext).execute(cat.getId());
}

我认为你必须在mCategoriesList.get(position)上调用setIsInitialized(true),而不是在cat上,因为当再次调用getView()时,mCategoriesList.get(position)总是返回未初始化的,因为你在@987654328上调用setIsInitialized(true) @,不在mCategoriesList中。

【讨论】:

  • 嗯。 mCategoriesList 是一个列表,我的意思是,是一个对象,而不是主要类型。所以我希望当我将一个对象(列表)分配给另一个对象时,不会复制对象,而是传递对它的引用,如果我稍后修改引用,那么应该修改原始对象。我说的对吗?
  • 哦,你是对的,我的错。但也许我知道问题出在哪里。
  • getView() 在滚动时只要有新行可见就会被调用。但是当调用 getView() 时,mTvUnread(您在 onProgressUpdate 中更新)始终是一个新实例。所以我的猜测是,当您更新 mTvUnread 时,它不再可用(可能泄漏,因为您将引用作为 AsyncTask 中的成员持有)?
  • 我建议当您的 AsyncTask 完成后,以某种方式将结果保存在 mCategoriesList 中,并为 mCategoriesList 的项目设置 isInit 标志,并在 getView 中仅检查是否设置了标志,如果是,则更新文本,如果没有,启动一个新的 asyncTask
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多