Ole*_*iov 4 android event-bus android-syncadapter android-fragments greenrobot-eventbus
我和EventBusGreenrobot 有问题.
我试图从我的同步适配器的后台服务发布事件,并在片段中捕获它以更新UI.
问题是当我尝试从同步适配器发布事件时,我在调试日志中得到以下内容:
No subscribers registered for event class olexiimuraviov.ua.simplerssreader.event.UpdateUIEvent No subscribers registered for event class org.greenrobot.eventbus.NoSubscriberEvent
我在其中注册片段onResume并取消注册onPause
@Override
public void onResume() {
super.onResume();
EventBus.getDefault().register(this);
if (mDebug) Log.d(LOG_TAG, EventBus.getDefault().isRegistered(this) + "");
}
@Override
public void onPause() {
super.onPause();
EventBus.getDefault().unregister(this);
}
Run Code Online (Sandbox Code Playgroud)
onResume中的日志语句显示片段已成功注册.
这是onEvent方法:
@Subscribe
public void onEvent(UpdateUIEvent event) {
if (mSwipeRefreshLayout.isRefreshing())
mSwipeRefreshLayout.setRefreshing(false);
}
Run Code Online (Sandbox Code Playgroud)
我试图用Background threadmode调用onEvent方法,但它没有帮助.
在此之后,我试图使用处理程序发布事件,但eventbus仍然找不到任何注册订阅者的事件.
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
EventBus.getDefault().post(new UpdateUIEvent());
}
});
Run Code Online (Sandbox Code Playgroud)
这是我的onPerform同步适配器方法:
@Override
public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) {
// Fetch data from server
} finally {
// close everything
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
Log.d(LOG_TAG, "Update event");
EventBus.getDefault().post(new UpdateUIEvent());
}
});
}
}
Run Code Online (Sandbox Code Playgroud)
如何使用Greenrobot将事件从同步适配器发送到片段EventBus?
TL;博士
你永远不用担心哪个线程你从后一个事件,但你不必担心它处理你张贴.您的同步适配器在与您的片段不同的进程中运行 - EventBus仅在创建它的过程中工作.
长版
您永远不需要启动不同的线程,甚至担心除了订阅事件之外的任何地方您都在哪个线程.
查看http://greenrobot.org/eventbus/documentation/delivery-threads-threadmode/了解更多详情,但语法非常简单:
@Subscribe(threadMode = ThreadMode.BACKGROUND)
public void thisMethodWillBeRunInABackgroundThread(DoLoginEvent event)
{
//Run some code that makes an HTTP request
}
Run Code Online (Sandbox Code Playgroud)
并在UI上运行一些东西:
@Subscribe(threadMode = ThreadMode.MAIN)
public void thisMethodWillBeRunOnTheUIThread(LoginSuccessfulEvent event)
{
//Run some code that touches the UI
}
Run Code Online (Sandbox Code Playgroud)
当你调用后()火同时关闭DoLoginEvent和LoginSuccessfulEvent它绝对不会不管你是在哪一个线程.
现在你遇到了真正的问题:似乎没有在订阅对象上捕获事件.
我怀疑这是因为您的同步适配器在不同的进程中运行.EventBus仅在创建过程中运行.
同步适配器(如BroadcastReceiver或Service)在单独的进程中运行,以允许您与服务器同步数据,而无需与应用程序本身进行任何交互.我的想法是,即使应用程序关闭,您也可以与服务器同步,将数据保存到数据库,然后当应用程序启动时,它会检查该数据库(快速)而不必与服务器同步(慢速).但是,如果同步适配器运行时您的应用程序处于活动状态,那么您希望保存到数据库,还要告诉应用程序有一些新信息吗?
因此,为了让您的同步适配器与您的应用程序通信,我建议您在片段/活动中设置BroadcastReceiver,然后从同步适配器广播意图.
这个机制与EventBus的概念非常相似,你甚至可以发送粘性意图!你的片段会监听这些意图,但只有在它活着的时候.如果您的同步适配器在您的应用程序关闭时发送广播,则没有任何反应.但是当片段启动并注册这些意图时,它将获得最后一个粘性.
public class LogFragment extends Fragment {
private LogReceiver mReceiver;
public class LogReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//you can call the EventBus from in here
}
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mReceiver = new LogReceiver();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
getActivity().registerReceiver(mReceiver, new IntentFilter("com.whatever.whatever"));
return view;
}
@Override
public void onDestroyView() {
getActivity().unregisterReceiver(mReceiver);
super.onDestroy();
}
}
Run Code Online (Sandbox Code Playgroud)
然后从同步适配器
Intent sendIntent = new Intent("com.whatever.whatever");
sendIntent.putExtra("SYNC_ADAPTER_EXTRA", "Your sync adapter says hi");
context.sendBroadcast(sendIntent);
Run Code Online (Sandbox Code Playgroud)