等待从数据库异步获取数据以填充列表视图的方法的最佳方法

时间:2016-06-21 11:35:10

标签: android multithreading listview asynchronous retrofit

我想用异步从DB中检索的数据填充listView, 问题是,如果我设置适配器,它会抛出空指针,因为数据还没有产生,当我收到数据时,一个方法被执行,所以我可以在这个方法中调用填充我的listview?我尝试将布局传递给这个类,以便在收到数据时直接填充listview,但是没有工作(没有发生)

我认为使用AsyncTask是一个好主意添加wait()并且当触发这个“检索器数据方法”时调用notify()但我不知道如何从另一个类的asynctask调用notify()...

我也不确定asynktask是否是最好的方法,任何想法? 如果有帮助我正在使用retrofit2

listview代码创建/填充

private List<TmOfsDTO> prepareList() {
    List<TmOfsDTO> list;
    try {
        // Create list of items
        ListObtainer listObtainer = new ListObtainer(this);
        list = listObtainer.getTmOfsDTOList(user); // this method returns list of objects from DB
    } catch (Exception e) {
        list = null;
        e.printStackTrace();
    }
    return list;
}

private void populateListView(List<TmOfsDTO> lista) {

    // Build Adapter
    OrderAdapter orderAdapter = new OrderAdapter(this, 0, lista);
    // orderAdapter.getView()

    Log.d("LSO", ".....");
    // Configure listview
    //View rootView = View.inflate(this, R.layout.activity_ordenes, null);
    ListView listView = (ListView) findViewById(R.id.lvOrdenes);
    listView.setAdapter(orderAdapter);
    //listView.invalidateViews();
    //listView.refreshDrawableState();
    Log.d("LSO", ".......");

上次更新:
** 当我收到数据,将适配器传递给类并调用时,我正确地做了通知:     orderAdapter.notifyDataSetChanged();

但问题是我缺少添加每个项目:     orderAdapter.add(奥登);

在通知之前,现在似乎工作得很好**

5 个答案:

答案 0 :(得分:0)

无论如何,你最好使用RecyclerView。这是新支持库的一部分,并且比旧的ListView更有效。

这里的一些关键问题是数据库是否是本地的。如果您在手机上有一个sqlite3数据库,那么您应该编写一些类,将数据库信息加载到可存储到数组中的对象中,并轻松传入RecyclerView.Adapter。

如果您正在远程加载,那么在尝试加载RecyclerView之前,使用AsyncTask将数据同步到手机上会好100%,否则您将收到这些错误。

您可以从远程数据库将一个项目加载到ArrayList中,将其传递给RecyclerView,然后从远程数据库继续加载,并在每个项目添加到列表时通知RecyclerView更改。

答案 1 :(得分:0)

当您在上面显示logcat时,lista为空。您将此列表传递给适配器。但是如果你没有初始化变量lista,它将抛出一个空指针异常。

建议初始化传递给适配器的List。然后,当数据进入时,您添加数据lista并调用方法adapter.notifyDataSetChanged()

以下似乎导致空指针异常

} catch (Exception e) {
        list = null;
        e.printStackTrace();
}

因此,除了初始化之外,您还应该不指定null。

答案 2 :(得分:0)

为适配器创建一个不同的构造函数,该构造函数不接收要在其中显示的数据。当你拥有它时,它不会崩溃。

要获取您的数据,请创建项目的本地List并使用以下内容填充:

public void setData(List<MyObject> data){
this.mData = data;
notifyDataSetChanged();
}

另外,不要忘记在getItem等方法中处理可能的空指针错误。

答案 3 :(得分:0)

让我们说我们在viewDidLoad方法中。我建议你做以下事情:

    你的适配器类中的
  • 创建公共方法:setData,它调用adapter.notifyDataSetChanged()
  • 通过传递回调函数
  • 向后端发送请求
  • 显示加载/进度对话框
  • 通过传递空数组(非空)来初始化适配器
  • 当触发回调并获得列表调用适配器的setData并隐藏进度对话框时。

答案 4 :(得分:0)

如果您正在使用 Fragments,只需在数据提取后再次调用 setAdapter()