- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我在首选项 Activity 中注册了一个广播接收器,并从(清醒的)IntentService 向它发送(同步)广播。显然 onReceive 在服务的线程上运行。这是我的错吗?是否记录了行为?
偏好 Activity :
public final class SettingsActivity extends BaseSettings {
private static CharSequence sMasterKey;
private CheckBoxPreference mMasterPref;
// Receiver
/** If the master preference is changed externally this reacts */
private BroadcastReceiver mExternalChangeReceiver =
new ExternalChangeReceiver();
public static void notifyMonitoringStateChange(Context ctx,
CharSequence action, boolean isToggling) {
final LocalBroadcastManager lbm = LocalBroadcastManager
.getInstance(ctx);
Intent intent = new Intent(ctx, ExternalChangeReceiver.class);
intent.setAction(action.toString());
intent.putExtra(TOGGLING_MONITORING_IN_PROGRESS, isToggling);
lbm.sendBroadcastSync(intent);
}
@Override
protected void onStart() {
super.onStart();
final LocalBroadcastManager lbm = LocalBroadcastManager
.getInstance(this);
lbm.registerReceiver(mExternalChangeReceiver, new IntentFilter(
ac_toggling.toString()));
}
@Override
protected void onStop() {
// may not be called in Froyo
final LocalBroadcastManager lbm = LocalBroadcastManager
.getInstance(this);
lbm.unregisterReceiver(mExternalChangeReceiver);
super.onStop();
}
private final class ExternalChangeReceiver extends BroadcastReceiver {
ExternalChangeReceiver() {}
@Override
@SuppressWarnings("synthetic-access")
public void onReceive(Context ctx, Intent intent) {
if (sMasterKey == null || mMasterPref == null) return; // if
// onPostReceive has not run this will be null
final String action = intent.getAction();
if (ac_toggling.equals(action)) {
final boolean isToggling = intent.getBooleanExtra(
TOGGLING_MONITORING_IN_PROGRESS, false);
Log.w(ExternalChangeReceiver.class.getSimpleName(),
"isToggling " + isToggling);
mMasterPref.setEnabled(!isToggling); // line 168 !!!
refreshMasterPreference(isToggling);
}
}
}
}
Intent 服务(位置监控):
SettingsActivity.notifyMonitoringStateChange(this, ac_toggling, true);
异常(E/AndroidRuntime):
FATAL EXCEPTION: IntentService[LocationMonitor]
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:4746)
at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:823)
at android.view.View.requestLayout(View.java:15473)
at android.view.View.requestLayout(View.java:15473)
at android.view.View.requestLayout(View.java:15473)
at android.view.View.requestLayout(View.java:15473)
at android.view.View.requestLayout(View.java:15473)
at android.view.View.requestLayout(View.java:15473)
at android.view.View.requestLayout(View.java:15473)
at android.view.View.requestLayout(View.java:15473)
at android.view.View.requestLayout(View.java:15473)
at android.widget.AbsListView.requestLayout(AbsListView.java:1819)
at android.widget.AdapterView$AdapterDataSetObserver.onChanged(AdapterView.java:813)
at android.widget.AbsListView$AdapterDataSetObserver.onChanged(AbsListView.java:5958)
at android.database.DataSetObservable.notifyChanged(DataSetObservable.java:37)
at android.widget.BaseAdapter.notifyDataSetChanged(BaseAdapter.java:50)
at android.preference.PreferenceGroupAdapter.onPreferenceChange(PreferenceGroupAdapter.java:238)
at android.preference.Preference.notifyChanged(Preference.java:1099)
at android.preference.Preference.setEnabled(Preference.java:726)
at gr.uoa.di.monitoring.android.activities.SettingsActivity$ExternalChangeReceiver.onReceive(SettingsActivity.java:168)
at android.support.v4.content.LocalBroadcastManager.executePendingBroadcasts(LocalBroadcastManager.java:297)
at android.support.v4.content.LocalBroadcastManager.sendBroadcastSync(LocalBroadcastManager.java:278)
at gr.uoa.di.monitoring.android.activities.SettingsActivity.notifyMonitoringStateChange(SettingsActivity.java:54)
at gr.uoa.di.monitoring.android.services.Monitor.abort(Monitor.java:241)
at gr.uoa.di.monitoring.android.services.LocationMonitor.doWakefulWork(LocationMonitor.java:103)
at com.commonsware.cwac.wakeful.WakefulIntentService.onHandleIntent(WakefulIntentService.java:94)
at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:65)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.os.HandlerThread.run(HandlerThread.java:60)
在模拟器 API 17 上
最佳答案
sendBroadcastSync()
确实在调用它的线程上运行(除非正在进行竞争)。它的实现should be :
public void sendBroadcastSync(Intent intent) { // directly calls executePendingBroadcasts
if (sendBroadcast(intent)) {
executePendingBroadcasts();
}
}
我不确定的比赛部分通过 sendBroadcast()
调用进入,如果它找到任何匹配的接收者(为此 Intent 向 LBM 注册),发送消息后返回 true到私有(private)处理程序与主循环相关联 - 缩写:
@Override
public boolean sendBroadcast(Intent intent) {
synchronized (mReceivers) {
final String action = intent.getAction();
final ArrayList<ReceiverRecord> entries = mActions.get(action);
if (entries == null) return false; // no receivers for that action
ArrayList<ReceiverRecord> receivers = new ArrayList<ReceiverRecord>();
for (ReceiverRecord receiver : entries) {
if (receiver.broadcasting) continue;
// match the intent
int match = receiver.filter.match(action,
intent.resolveTypeIfNeeded(mAppContext.getContentResolver()),
intent.getScheme(), intent.getData(),
intent.getCategories(), "LocalBroadcastManager");
if (match >= 0) {
receivers.add(receiver);
receiver.broadcasting = true;
}
}
final int size = receivers.size();
if (size == 0) return false; // no receivers for this intent
for (int i = 0; i < size; i++) {
receivers.get(i).broadcasting = false;
}
mPendingBroadcasts.add(new BroadcastRecord(intent, receivers));
if (!mHandler.hasMessages(MSG_EXEC_PENDING_BROADCASTS)) {
mHandler.sendEmptyMessage(MSG_EXEC_PENDING_BROADCASTS);
}
return true;
}
}
哪里:
mHandler = new Handler(context.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_EXEC_PENDING_BROADCASTS:
executePendingBroadcasts();
break;
default:
super.handleMessage(msg);
}
}
我不确定主线程和正在执行的线程 sendBroadcastSync()
之间是否存在竞争 - 所以 executePendingBroadcasts()
将在主线程上运行线。如果不是,则 executePendingBroadcasts()
在线程上运行 sendBroadcastSync
并运行 directly calls接收者的onReceive
有一天我应该研究为什么(在 executePendingBroadcasts 中)synchronized(mReceivers)
而不是 synchronized(mPendingBroadcasts)
。
关于android - 在 LocalBroadcastManager 注册的 BroacastReceiver 的 onReceive() 在哪个线程运行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20820244/
我正在编写一个应用程序来跟踪 Google map 上的路线历史记录。它会每 5 分钟获取一次设备的当前位置,并通过网络服务将数据发送到服务器。 此代码用于从 MainActivity 调用 Broa
我正在开发一款安卓应用。此应用程序分为 2 个应用程序部分,一个应用程序部分作为库部分,第二部分处理正常任务。 我在图书馆应用程序中实现 GCM 推送通知,因此,我在图书馆应用程序和第二个应用程序上注
我在首选项 Activity 中注册了一个广播接收器,并从(清醒的)IntentService 向它发送(同步)广播。显然 onReceive 在服务的线程上运行。这是我的错吗?是否记录了行为? 偏好
我是一名优秀的程序员,十分优秀!