如何从Runnable更新UI?

时间:2014-12-11 04:10:58

标签: java android multithreading android-fragments

我需要从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中启动runnable的代码

/**
 * 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 个答案:

答案 0 :(得分:3)

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()是完全合理的。

答案 1 :(得分:2)

请查看AsyncTask以从线程更新UI:

http://developer.android.com/reference/android/os/AsyncTask.html

以下是上述链接中的重点:

  

类概述AsyncTask可以正确,轻松地使用UI线程。   此类允许执行后台操作和发布结果   在UI线程上,无需操纵线程和/或处理程序。

     

AsyncTask旨在成为Thread和Handler的辅助类   并不构成通用的线程框架。 AsyncTasks   理想情况下应该用于短期操作(几秒钟的时间)   大多数。)如果你需要保持线程长时间运行,   强烈建议您使用提供的各种API   java.util.concurrent包,如Executor,ThreadPoolExecutor和   FutureTask。

     

异步任务由在a上运行的计算定义   后台线程,其结果发布在UI线程上。一个   异步任务由3种泛型类型定义,称为Params,   进度和结果,以及4个步骤,称为onPreExecute,doInBackground,   onProgressUpdate和onPostExecute。

答案 2 :(得分:2)

您可以使用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
                }
            });
        }
    }
}

答案 3 :(得分:1)

您无法从runnable更新UI。您需要处理程序来更新UI。有关详细信息,请参阅this

答案 4 :(得分:0)

UI只能由创建它的线程修改。在大多数情况下是由UI线程。所以你需要使用runOnUiThread方法进行更新。祝你好运

答案 5 :(得分:0)

我知道答案有点不同。但我希望你能看到Android Annotations。哪个非常好用。我只将它们用于背景和Ui线程。通过在方法名称上编写@Background来完成后台线程中的每个任务。并在UI线程中进行所有UI更新。我建议你只检查一次。 http://androidannotations.org/ 谢谢 至于你的答案是关注。您无法从runnable更新UI。请参阅asyn任务以更新您的Ui。

答案 6 :(得分:0)

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

getActivity().runOnUiThread(new Runnable() {

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

答案 7 :(得分: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
}
顺便说一下,你可以通过事件传递任何数据,这是你的自定义类!请阅读手册如何设置此lib,注册总线活动。它非常有用且易于使用

答案 8 :(得分:0)

您可以创建一个Runnable,然后发布到主线程。来自Google Processes and Threads

上的开发者页面
  

此实现是线程安全的:后台操作已完成   从一个单独的线程,而ImageView总是被操纵   UI线程。

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();
}