问题是,当服务器触发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线程中执行更新,其中包含ListViews
或TextView
答案 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);
}
}
}