EventBus仅在放入Handler时有效

时间:2015-12-12 13:17:16

标签: android android-fragments android-viewpager realm

我的ViewPager包含三个不同的Fragments,每个片段都有自己的API调用。让我们说第一个片段是从API请求某些东西。返回回调,然后我将其保存到本地Realm数据库,之后我将EventBus发送给Fragment。问题是我得到No subscribers registered for event class错误并且没有任何反应。

过了一段时间,我设法用这种方式解决了这个问题:

final GetInfoResponse response = new GetInfoResponse(databaseService.getInfo());
new Handler().post(new Runnable() {
                    public void run() {
                        EventBus.getDefault().post(response);
                    }
                });

如果我将EventBus放入Handler中,则Event会正确传递给Fragment。

我在想,在从数据库获取数据时,Realm可能正在切换线程。但我不确定。另一方面,如果我没有进行本地保存并直接从REST回调发送EventBus,那么一切正常。

编辑: GetInfo方法

public List<Information> getInfo() {
        List<Information> informationList;
        Realm realm = Realm.getInstance(getConfig(context));
        realm.beginTransaction();
        RealmResults<Information> realmList = realm.where(Information.class).findAll();
        informationList = new ArrayList<>(realmList);
        realm.commitTransaction();
        return informationList;
    }

为什么会这样,我怎样才能做得更好?

编辑2: 经过@EpicPandaForce提出的变更。 这是我的代码结构和调用API的路径。 我有碎片。我们称之为InfoFragment。在onCreateView我这样做:

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            View view = inflater.inflate(R.layout.info, container, false);
            realm = Realm.getInstance(DatabaseConfiguration.getConfig(getActivity()));
            DataManager dataManager = new DataManager(realm, getActivity());
            dataManager.getInfo();
            return view;
        }

        public void onEvent(GetFaqCategoriesResponse response) {
        ...
        }

        @Override
        public void onStart() {
            super.onStart();
            EventBus.getDefault().register(this);
        }

        @Override
        public void onStop() {
            EventBus.getDefault().unregister(this);
            super.onStop();
        }

现在,我的DataManager看起来像这样:

public DataManager(Realm realm, Context context) {
        this.context = context;
        databaseService = new DatabaseService(realm);
    }

public void getInfo() {
        if (ConnectionUtils.isNetworkAvailable(context)) {
            ServerService.getInfo(this);
        } else {
            final GetInfoResponse response
                    = new GetInfoResponse(databaseService.getInfo());
            new Handler().post(new Runnable() {
                public void run() {
                    EventBus.getDefault().post(response);
                }
            });
        }
    }

我的DatabaseService

private Realm realm;

public SupportDatabaseService(Realm realm) {
    this.realm = realm;
}

public List<Info> getInfo() {
    RealmResults<Info> realmList = realm.where(Info.class).findAll();
    return new ArrayList<>(realmList);
}

我正在使用Realm realm.close() onDestroyView中的InfoFragment关闭{{1}}个实例。

1 个答案:

答案 0 :(得分:1)

要自动更新所有looper线程上的Realms,Realm sends a message to the main thread looper's handler在提交事务时开始更新。因此,除非您订阅了RealmListener中的Realm的更改(我不推荐,因为它每次修改领域都会更新!),您只会在下一个处理程序循环运行时收到有关它的通知。如果您使用onEvent(),那么就像default threading mode所指定的那样,您的事件将立即传递,而不是通过处理程序(在下一次迭代时发送runnable在另一个looper线程上执行)。

基本上,如果您不通过处理程序发送它,那么在接收事件时,其他线程的Realm将不会更新。如果要将这些Realm对象从主线程发送到主线程,则可以使用onEventMainThread()而不是onEvent()自动将其通过处理程序传递给主线程。

顺便说一句,你正在错误地使用Realm,你打开的Realm实例也应该被关闭,但是只能在同一个线程上访问与给定Realm相关联的Realm对象,并且只能从一个开放的领域。您无需打开新领域来执行查询,您可以使用在findAll()中打开的Realm实例在主线程上使用onCreateView(),同时在onDestroyView()中关闭它},findAll()作为惰性查询执行,因此不会占用大量内存。即使你实际上没有做任何写作,你也开始并进行交易......? :P