从另一个线程更新主线程中的ListView

时间:2010-05-27 09:07:56

标签: android

我有一个单独的线程来运行从互联网上获取数据。之后,我想通过调用adapter.notifyDataSetChanged()更新主线程中的ListView。但它不起作用。任何解决方法?感谢。

5 个答案:

答案 0 :(得分:13)

使用AsyncTask(http://developer.android.com/reference/android/os/AsyncTask.html)。

onPostExecute(...)方法中调用 adapter.notifyDataSetChanged()

有关详情,请参阅:http://android-developers.blogspot.com/2009/05/painless-threading.html

答案 1 :(得分:12)

总的来说,好的建议是 http://android-developers.blogspot.com/2009/05/painless-threading.html

我个人使用自定义线程(扩展线程的类),但通过Message发送响应给UI线程。所以在线程的run()函数中有:

Message msg;
msg = Message.obtain();
msg.what = MSG_IMG_SET;                     
mExtHandler.sendMessage(msg);

UI线程定义了一个消息处理程序。

private Handler mImagesProgressHandler;

public void onCreate(Bundle bundle) {

    mImagesProgressHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {             
            case LoadImagesThread.MSG_IMG_SET:
                mArrayAdapter.setBitmapList(mImagesList);
                mArrayAdapter.notifyDataSetChanged();
                break;
            case LoadImagesThread.MSG_ERROR:
                break;
            }
            super.handleMessage(msg);
        }
    };                 

这实际上比AsyncTask更容易。

答案 2 :(得分:9)

或者,将消息发布到listview的消息队列(将在UI线程上执行):

list.post(new Runnable() {                  
    @Override
    public void run() {
       adapter.notifyDataSetChanged();

    }
}); 

答案 3 :(得分:3)

您可以将RxJavaRetrofit的组合用于此目的。

以下是如何做到的。我将使用GitHub API作为示例。

为您的HTTP API创建Java接口。

public interface GitHubService {
    @GET("users/{user}/repos")
    Observable<List<Repo>> listRepos(@Path("user") String user);
}

使用Observable会将响应转换为流。每个事件都是回购清单。

使用Retrofit类生成GitHubService接口的实现。您可能会或可能会或不会提供自定义HTTP客户端。

Retrofit retrofit = new Retrofit.Builder()
            .baseUrl("https://api.github.com/")
            .client(okHttpClient) // OkHttp Client
            .addConverterFactory(GsonConverterFactory.create())
            .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
            .build();

GitHubService service = retrofit.create(GitHubService.class);

现在是Rx的一部分。您必须添加订阅者才能收听服务器发回的响应。换句话说,对它做出反应

service.listRepos("octocat")
.subscribeOn(Schedulers.io()) // 1
.observeOn(AndroidSchedulers.mainThread()) // 2
.flatMap(Observable::from) // 3
.subscribe(repoList -> { // 4
    // Update the list view
    // notifyDataSetChanged
});

这里有用数字评论的行 -

1 - 它告诉操作系统使用哪个线程进行呼叫。我们正在为此选择IO线程。

2 - 它告诉操作系统使用哪个线程来监听响应。我们在主线程上执行此操作,并在收到响应时更新UI。

3 - 这一行展示了Rx的真正魔力。这个简单的小行将响应列表转换为单个对象。因此,我们将对每个对象做出反应,而不是对整个列表做出反应。您可以阅读更多相关信息here

4 - 这条线实际上定义了什么样的反应&#39;将被展示给该活动。您可以在此处更新适配器。

更精细的订阅者看起来像这样 -

new Subscriber<Repo>() {
    @Override
    public void onCompleted() {

    }

    @Override
    public void onError(Throwable e) {

    }

    @Override
    public void onNext(Repo repo) {

    }
}

P.S。 - 我在上面的例子中使用过lambdas。您可以通过here添加该内容。

答案 4 :(得分:-1)

这里的诀窍是放置

的位置
  

mAdapter.notifyDataSetChanged();

这是一个简单的例子:

mRecyclerView = (RecyclerView) rootView.findViewById(R.id.recycler_view);
mAdapter = new myAdapter(......);
mAdapter.notifyDataSetChanged();
mRecyclerView.setAdapter(mAdapter);

这对我来说非常完美。