Android - 为列表视图填充适配器的异步任务

Posted

技术标签:

【中文标题】Android - 为列表视图填充适配器的异步任务【英文标题】:Android - asynctask that fills an adapter for a listview 【发布时间】:2015-03-26 02:43:33 【问题描述】:

流程基本上是这样的:当一个片段被创建时(或者当用户滑动刷新布局时),一个 AsyncTask 被执行。 ASyncTask 从 URL 检索信息并设置适配器,然后将其分配给 ListView。

这是片段的代码:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                     Bundle savedInstanceState) 

    View rootView = inflater.inflate(R.layout.tasks_page, container, false);
    mSwipeRefreshLayout = (SwipeRefreshLayout)
    rootView.findViewById(R.id.list_container);
    mSwipeRefreshLayout.setOnRefreshListener(this);
    mSwipeRefreshLayout.setColorSchemeResources(android.R.color.holo_blue_bright,    
    android.R.color.holo_green_light, android.R.color.holo_red_light);

    lv = (ListView) rootView.findViewById(android.R.id.list);
    getTasks();

    return rootView;


private void getTasks() 
    new TasksRetriever(mSwipeRefreshLayout,tasksAdapter,lv).execute();


@Override
public void onRefresh() 
    mSwipeRefreshLayout.setRefreshing(true);
    new Handler().postDelayed(new Runnable() 
                @Override
                public void run() 
                    getTasks();
                
            , 1000);

TaskRetriever 构造函数是:

public TasksRetriever(SwipeRefreshLayout srl, TasksAdapter ta, ListView lv) 
    adpt = ta;
    this.srl = srl;
    this.lv = lv;

而 postExecute 是:

@Override
protected void onPostExecute(List<TasksItem> result) 
    super.onPostExecute(result);
    dialog.dismiss();
    if (adpt == null) adpt = new TasksAdapter(result);
    else adpt.setItemList(result);
    lv.setAdapter(adpt);
    adpt.notifyDataSetChanged();
    srl.setRefreshing(false);

尚不确定它是否有效,但我想知道我是否走在正确的轨道上,因为它对我来说看起来并不干净。另一方面,在我真正拥有数据之前,我无法创建适配器并将其分配给 ListView……这是考虑好还是我做错了?

【问题讨论】:

您可以创建一个空适配器并稍后填充它 - 在 AsyncTask 中 你在正确的轨道上。如果您总是向适配器加载一个新列表(而不是添加 itens),则可以创建一个新适配器并将其设置为列表视图(顺便说一下,您可以通过 listView.getAdapter() 获取适配器)。我还建议您在 TasksRetriever 中添加一个 progressDialog,因为如果用户在加载列表时触摸或操作设备,可能会导致 ui 冻结或出现不良行为。 适配器是公共类 TasksAdapter extends ArrayAdapter 所以我做了 super(Utils.context,android.R.layout.simple_list_item_1, itemList); itemList 包含列表 - 我可以传递 null 吗?或者也许我不需要超级? 因此将所有 3 个对象(布局、适配器、列表视图)传递给 asynctask,是正确的方法,我只需要按照此处的建议重新组织代码? 【参考方案1】:

我会在您的列表视图下的 onCreate() 方法中设置列表适配器,并将其设为实例变量(不是本地变量),以便 Async 任务可以按如下方式访问它,即

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                     Bundle savedInstanceState) 

    lv = (ListView) rootView.findViewById(android.R.id.list);
    mAdpt = new TasksAdapter(null);
    lv.setAdapter(mAdpt);


然后在你的 onPostExecute()

@Override
protected void onPostExecute(List<TasksItem> result) 
    dialog.dismiss();  
    mAdpt.clear();
    for( TaskItem ti : result ) 
    
      mAdpt.add( ti );
    
    mAdpt.notifyDataSetChanged();
    srl.setRefreshing(false);

还要确保在 getView() 方法中将 null 值传递给适配器。

希望这会有所帮助。

【讨论】:

请注意,mAdpt.clear 应该是 mAdpt.clear();【参考方案2】:

您可以创建一个空适配器并稍后在 AsyncTask 中填充它

你的onPostExecute() 应该是这样的:

@Override
protected void onPostExecute(List<TasksItem> result) 
    dialog.dismiss();
    if (adpt == null)
      adpt = new TasksAdapter(result);
      lv.setAdapter(adpt);
    else
      adpt.clear();
    
    for( TaskItem ti : result ) adpt.add( ti );
    adpt.notifyDataSetChanged();
    srl.setRefreshing(false);

【讨论】:

在适配器中我有 public void setItemList(List itemList) this.itemList = itemList; - 我猜使用 adpt.clear;而 adpt.add() 是更好的编码还是没有太大区别? @Amos 资源分配有明显区别。您应该只创建一次adapter,并根据需要修改基础数据集。创建一个新的Adapter 是一项繁重的工作。因此,为什么我赞成 Andy B 的回答。 您可以对支持列表做任何您想做的事情 :) 问题是,在您致电 notifyDataSetChanged() 之前,更改不会反映在 listview 中。唯一可以调用它的地方是onPostExcecute() 谢谢,我想知道我正在编写好的/干净的代码,而不仅仅是一个工作代码(这很容易:))

以上是关于Android - 为列表视图填充适配器的异步任务的主要内容,如果未能解决你的问题,请参考以下文章

Android - 使用片段和简单的光标适配器填充列表视图

我的列表视图没有填充,我的适配器有问题吗?

如何在 Android 中使用异步任务通过数组列表更新列表视图?

列表视图

Android:列表视图/适配器中不再显示视图?

在android的片段中设置列表视图适配器