如何从Runnable中更新用户界面?

4

我需要从Runnable更新UI。我的逻辑如下。

我在片段生命周期的onCreate中启动了runnable。而且,runnable实例负责请求网络。问题是当runnable实例从网络获取数据后,我不知道如何更新片段。

以下是CustomFragment.java中在片段中启动runnable的代码。

public void onCreate(Bundle savedInstanceState) {
    Log.d(DEBUG_TAG, "onCreate");
    super.onCreate(savedInstanceState);

    accountMgr.requestAccountInfo();

}

在AccountManager.java中启动可运行代码的代码:

/**
 * request Account info from server
 */
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public void requestAccountInfo() {
    Account act = getCurrentAccount();
    Thread t = new Thread(new RequestAccountInfoTask(act));
    t.start();
}

/**
 * automatically update Account info, like space usage, total space size, from background.
 */
 class RequestAccountInfoTask implements Runnable {

    private Account account;

    public RequestAccountInfoTask(Account account) {
        this.account = account;
    }

    @Override
    public void run() {
        doRequestAccountInfo(account);

    }
}
9个回答

4

runOnUiThread() 需要 Activity 引用。有其他的选择。您不需要将 Activity 引用传递给您的 Thread。您始终可以使用主线程获得UI处理程序。在任务完成后,通过传递其他参数,如界面更新接口,来更新片段。

class RequestAccountInfoTask implements Runnable {

    private Account account;
    private Handler mHandler;
    public RequestAccountInfoTask(Account account) {
        this.account = account;
        mHandler = new Handler(Looper.getMainLooper());
    }

    @Override
    public void run() {
        doRequestAccountInfo(account);
        //use the handler
    }
}

任何在实例化的Handler上运行的内容都会在UI线程上执行。
当然,使用runOnUiThread()是完全合理的。

我已经实现了这个注释,一些参考在这里 - Logan Guo

3

你可以使用Activity的runOnUIThread方法。

以下代码可能对你有所帮助:

class RequestAccountInfoTask implements Runnable {

    private Account account;

    public RequestAccountInfoTask(Account account) {
        this.account = account;
    }

    @Override
    public void run() {
        doRequestAccountInfo(account);
        if (getActivity() != null) {
            getActivity().runOnUiThread(new Runnable() {

                @Override
                public void run() {
                    // you can update fragment UI at here
                }
            });
        }
    }
}

2
请参考AsyncTask更新UI线程的方法:
请查看以下链接:http://developer.android.com/reference/android/os/AsyncTask.html 以下是上述链接的亮点:
类概述:AsyncTask可使UI线程正确、轻松地使用。该类允许执行后台操作,并在UI线程上发布结果,无需操纵线程和/或处理程序。
AsyncTask旨在成为Thread和Handler周围的助手类,而不构成通用的线程框架。异步任务应理想地用于简短的操作(最多几秒钟)。如果您需要长时间运行线程,强烈建议使用java.util.concurrent包提供的各种API,例如Executor、ThreadPoolExecutor和FutureTask。
异步任务由在后台线程上运行的计算及其结果在UI线程上发布组成。异步任务由3个泛型类型(称为Params、Progress和Result)和4个步骤(称为onPreExecute、doInBackground、onProgressUpdate和onPostExecute)定义。

1

我建议使用AsynTask,或者你可以尝试这个方法

getActivity().runOnUiThread(new Runnable() {

                @Override
                public void run() {
                    Toast.makeText(getActivity(), "ON UI Thread", Toast.LENGTH_LONG).show();
                }
            });

1

你不能从runnable中更新UI。你需要使用Handler来更新UI。查看this获取更多信息。


这个例子直接从Google自己的页面中复制,可以在UIThread中运行。https://developer.android.com/guide/components/processes-and-threads.html - Cameron Lowell Palmer

1

UI只能由创建它的线程修改。在大多数情况下,是由UI线程完成的。因此,您需要使用runOnUiThread方法进行更新。祝好运。


0
你可以使用事件总线来实现 - http://square.github.io/otto/。这很简单。只需在需要更新UI时从你的线程发送事件,就像这样:
...
//in the end of your heavy job:
bus.post(new YourEvent());

在你的Activity中创建方法:

@Subscribe
public void onYourEvent(YourEvent event) {
    //do what you want there
}

顺便说一下,你可以通过事件传递任何数据,包括自定义类!请阅读手册了解如何设置此库,为总线注册活动。它非常有用且易于使用。


0

我知道这个回答有点不同。但是我想让你了解一下Android Annotations。这些注解非常容易使用。我只在后台线程和UI线程中使用它们。通过在方法名上添加@Background,将每个任务都放在后台线程中执行。然后,在UI线程中进行所有的UI更新。我建议你去看一下这个链接http://androidannotations.org/。 谢谢! 至于你的问题,你不能从Runnable中更新UI。可以考虑使用异步任务来更新你的UI。


0

您可以创建一个Runnable对象,然后将其发布到主线程。此内容摘自Google的进程和线程开发者页面。

此实现是线程安全的:在单独的线程中执行后台操作,同时从UI线程始终操作ImageView。

public void onClick(View v) {
    new Thread(new Runnable() {
        public void run() {
            // a potentially  time consuming task
            final Bitmap bitmap =
                    processBitMap("image.png");
            mImageView.post(new Runnable() {
                public void run() {
                    mImageView.setImageBitmap(bitmap);
                }
            });
        }
    }).start();
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接