Android如何从其他类更新(UI线程)(真的吗?)

时间:2015-02-23 19:33:29

标签: java android android-asynctask google-cloud-messaging

您可能了解Google Cloud Messaging

问题是,当服务器触发gcm消息时,我的应用程序会收到来自Google Play服务的捆绑包,这发生在GcmBroadcastReceiver.java。在这里,我可以将这些数据发送到其他类,以便从服务器附加一些信息..好吧。当我尝试更新UI线程中的一些视图时,我陷入困境。

我该怎么做?

想象一下,当我声明视图等时,MainActivity.java是UI线程。

我尝试在这里创建一个公共静态方法,可以通过这种方式由GcmBroadcastReceiver.java直接调用:MainActivity.*updateUI*(args..),但它会抛出此异常:

android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

有人可以试着解释一下吗?我也知道asyncTask但我无法想象它是如何工作的。我还发现一些页面解释了由UI线程触发的事件,就像在后台执行某些任务的runnables一样。我在搜索这样的东西:

MainActivity extends Activity{

    ...
    protected void onCreate(Bundle blabla)..{

    setContentView(R.layout.blabla);

    registerSomeEvent(this);

    }

    private void handleEvent(Bundle ...){

    ... do stuff with the data provided in the UI thread

    }

} 

GcmBroadcastReceiver处,当gcm推送一些数据时,触发该魔术事件,以便在UI线程中执行更新,其中包含ListViewsTextView

等视图

2 个答案:

答案 0 :(得分:3)

一种方法是使用use LocalBroacastManager。关于如何实现,how to use LocalBroadcastManager?有一个很好的例子。

  

LocalBroadcast Manager是一个帮助程序,用于注册和发送Intent广播到进程中的本地对象。您正在播放的数据不会离开您的应用,因此无需担心泄露私人数据。

您的活动可以注册此本地广播。从GCMBroadcastReceiver开始,当您在GcmBroadcastReceiver中收到内容时,您会发送本地广播。在Activity内,您可以收听广播。这样,如果活动位于最前面/处于活动状态,它将接收广播,否则不会。因此,每当您收到本地广播时,如果活动开放,您可以执行所需的操作。这就像对活动说“嘿活动,我收到了一条消息。用它做任何你想做的事情”。

如果您想为整个应用程序做,那么您可以使所有活动扩展为抽象活动。在这个抽象活动类中,你可以为这个'LocalBroadcast'注册它。其他方式是在你的所有活动中注册LocalBroadcast(但是你必须管理你将如何只显示一次消息)。

答案 1 :(得分:1)

您可以在MainActivity中使用处理程序,以便与UI Thread进行通信。

Communicating with the UI Thread

    public class MainActivity extends Activity{
    public static final int NEW_DATA_AVAILABLE = 0; 
    public static final Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
            case MainActivity.NEW_DATA_AVAILABLE: 
                 String newData = msg.getData().getString(MyClass.DATA);
                 //Do some stuff with newData
                break;
            }
        }
    };
}

并在非活动类

public class MyClass implements Runnable{
    Thread thread;
    public final static String DATA = "new_data"; 
    public MyClass(){
        thread = new Thread(this);
        thread.start();
    }


    @Override
    public void run() {
        while(true){
            try{
                Thread.sleep(1000);
            }catch(Exception e){
                e.printStackTrace();
            }
            Message msg = mHandler.obtainMessage(MainActivity.NEW_DATA_AVAILABLE);
            Bundle bundle = new Bundle();
            bundle.putString(DATA, "We have received new data");
            msg.setData(bundle);
            MainActivity.handler.sendMessage(msg);
        }

    }

}