2015-02-23 72 views
0

你可能知道Google Cloud Messaging的Android如何更新从其他类(UI线程)(真的吗?)

的问题是,当一个GCM消息由服务器触发,我的应用程序会收到来自谷歌播放服务捆绑,这发生在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

+0

不要调用静态方法,在你的'MainActivity'创建一个广播接收器,然后在你的'GcmBroadcastReceiver'发送广播到您的活动告诉它该怎么做(刷新/更新) – tyczj 2015-02-23 19:44:24

回答

3

一种方式进行更新是使用使用LocalBroacastManager。关于如何实施,how to use LocalBroadcastManager?上有一个很好的例子。

LocalBroadcast Manager是注册并发送Intents广播到您的过程中的本地对象的助手。您所播放的数据不会离开您的应用,因此不需要担心泄露私人数据。“

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

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

+0

好的,但是如果每个活动都有他自己的“localBoardcast”..当gcm从服务器发出时会触发哪一个? – k1r0s 2015-02-23 19:48:01

+0

我假装建立一个基本上共享设备之间项目列表的应用程序。像Google Keep一样。 – k1r0s 2015-02-23 19:49:18

+0

所有那些注册特定本地广播的活动都会收到它。如果您只需要一项活动就可以在一项活动中注册广播。如果你注册了多个活动,你可以选择根据你所在的活动来采取行动。如果你只是想让它触发一次,你可以在'abstract'活动中声明它,并让所有其他活动扩展它。这取决于你如何设计你当前的应用程序。 – 2015-02-23 19:54:37

1

您可以在MainActivity中使用处理程序以便与UI线程通信。

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

    } 

} 
+0

谢谢:)以前的回答是最准确的 – k1r0s 2015-02-23 20:45:37