I am currently working on Fragments
that was created under Activities
with FragmentPagerAdapter
. I used GreenRobot's EventBus 3.0 to return some AsyncTasks I created from a service class. However, since these two fragments are created one after the other, the return of the eventbus' post sticky got the subscribed fragments mixed up. I've scoured over stackoverflow, did what the others did (e.g. put the eventBus register to onStart and OnStop, etc..) and I still can't see even a similar issue. Hope you can help me. Thanks!
Here's are my two fragments : (I've omitted some of the unnecessary codes)
1. Status Fragment
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.e(TAG, "StatusFragment onCreateView");
eventBus = EventBus.getDefault();
eventBus.register(this);
StatusService statusService = StatusService.newInstance(getContext());
statusService.getStatusList(); //Async Task to call onReturnAdapter once finished
return mRecyclerView;
}
@Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
public void onReturnList(List<Status> statuses) {
Log.e(TAG, "onReturnList");
mAdapter = new StatusRecyclerAdapter(statuses);
mRecyclerView.setAdapter(mAdapter);
eventBus.removeStickyEvent(statuses);
}
@Override
public void onStop() {
Log.e(TAG, "onStop");
eventBus.unregister(this);
super.onStop();
}
2. Status Service - Service class for Status Fragment
public void getStatusList () {
Log.e(LOG_TAG, "getStatusList");
//do some async tasks here
returnList(statuses);
}
private void returnList(List<Status> statuses) {
Log.e(LOG_TAG, "returnList");
eventBus.postSticky(statuses);
}
3. Chart Fragment
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.e(LOG_TAG, "onCreateView");
eventBus = EventBus.getDefault();
eventBus.register(this);
chartService = ChartService.newInstance(getContext());
chartService.getDateResult(new DbRequestFeelings());
return view;
}
@Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
public void onReturnResults(List<Result> results) {
Log.e(LOG_TAG, "onReturnResults");
chartService.setupPieChart(results, feelingsPieChart);
}
@Override
public void onStop() {
eventBus.unregister(this);
super.onStop();
}
4. Chart Service
public void getDateResult(final DbRequest dbRequest) {
Log.e(LOG_TAG, "getDateResult");
//do some async tasks
returnResults(results);
}
private void returnResults(List<Result> results) {
Log.e(LOG_TAG, "returnResults");
eventBus.postSticky(results);
}
5. Result Class
public class Result {
....
}
6. Status Class
public class Status {
...
}
So every time the fragments were created, they call on their service class which in turn posts the List<Status>
and List<Results>
almost one after the other. Due to this, it created a confusion where it says that
03-11 11:48:19.685 15148-15148/com.paularagones.moode E/EventBus﹕ Could not dispatch event: class java.util.ArrayList to subscribing class class com.paularagones.moode.Fragments.ChartFragment
java.lang.ClassCastException: com.paularagones.moode.Models.Status cannot be cast to com.paularagones.moode.Models.Result
Here's the full stack trace :
03-11 11:48:19.589 15148-15148/com.paularagones.moode E/Moode-StatusFragment﹕ StatusFragment onCreate
03-11 11:48:19.589 15148-15148/com.paularagones.moode E/Moode-StatusFragment﹕ StatusFragment onCreateView
03-11 11:48:19.605 15148-15148/com.paularagones.moode E/StatusService﹕ getStatusList
03-11 11:48:19.609 15148-15148/com.paularagones.moode E/ChartFragment﹕ onCreateView
03-11 11:48:19.613 15148-15148/com.paularagones.moode E/ChartService﹕ newInstance
03-11 11:48:19.621 15148-15148/com.paularagones.moode E/ChartService﹕ getDateResult
03-11 11:48:19.681 15148-15148/com.paularagones.moode E/RecyclerView﹕ No adapter attached; skipping layout
03-11 11:48:19.681 15148-15148/com.paularagones.moode E/StatusService﹕ returnList
03-11 11:48:19.681 15148-15148/com.paularagones.moode E/Moode-StatusFragment﹕ onReturnList
03-11 11:48:19.681 15148-15148/com.paularagones.moode E/ChartFragment﹕ onReturnResults
03-11 11:48:19.685 15148-15148/com.paularagones.moode E/EventBus﹕ Could not dispatch event: class java.util.ArrayList to subscribing class class com.paularagones.moode.Fragments.ChartFragment
java.lang.ClassCastException: com.paularagones.moode.Models.Status cannot be cast to com.paularagones.moode.Models.Result
at com.paularagones.moode.Services.ChartService.getData(ChartService.java:147)
at com.paularagones.moode.Services.ChartService.setupPieChart(ChartService.java:129)
at com.paularagones.moode.Fragments.ChartFragment.onReturnResults(ChartFragment.java:116)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at org.greenrobot.eventbus.EventBus.invokeSubscriber(EventBus.java:485)
at org.greenrobot.eventbus.EventBus.postToSubscription(EventBus.java:420)
at org.greenrobot.eventbus.EventBus.postSingleEventForEventType(EventBus.java:397)
at org.greenrobot.eventbus.EventBus.postSingleEvent(EventBus.java:370)
at org.greenrobot.eventbus.EventBus.post(EventBus.java:251)
at org.greenrobot.eventbus.EventBus.postSticky(EventBus.java:292)
at com.paularagones.moode.Services.StatusService.returnList(StatusService.java:80)
at com.paularagones.moode.Services.StatusService.access$100(StatusService.java:24)
at com.paularagones.moode.Services.StatusService$2.onNext(StatusService.java:72)
at com.paularagones.moode.Services.StatusService$2.onNext(StatusService.java:59)
at rx.Observable$30.onNext(Observable.java:8069)
at rx.observers.SafeSubscriber.onNext(SafeSubscriber.java:139)
at rx.internal.operators.OperatorObserveOn$ObserveOnSubscriber.pollQueue(OperatorObserveOn.java:202)
at rx.internal.operators.OperatorObserveOn$ObserveOnSubscriber$2.call(OperatorObserveOn.java:162)
at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55)
at android.os.Handler.handleCallback(Handler.java:615)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4745)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
03-11 11:48:19.685 15148-15148/com.paularagones.moode E/ChartService﹕ returnResults
03-11 11:48:19.685 15148-15148/com.paularagones.moode E/Moode-StatusFragment﹕ onReturnList
03-11 11:48:19.685 15148-15148/com.paularagones.moode E/ChartFragment﹕ onReturnResults
03-11 11:48:19.693 15148-15148/com.paularagones.moode E/StatusRecyclerAdapter﹕ onCreateViewHolder
03-11 11:48:19.697 15148-15148/com.paularagones.moode E/StatusRecyclerAdapter﹕ onBindViewHolder
03-11 11:48:19.709 15148-15148/com.paularagones.moode E/AndroidRuntime﹕ FATAL EXCEPTION: main
java.lang.ClassCastException: com.paularagones.moode.Models.Result cannot be cast to com.paularagones.moode.Models.Status
at com.paularagones.moode.Adapters.StatusRecyclerAdapter.onBindViewHolder(StatusRecyclerAdapter.java:101)
at com.paularagones.moode.Adapters.StatusRecyclerAdapter.onBindViewHolder(StatusRecyclerAdapter.java:28)
at android.support.v7.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:5277)
at android.support.v7.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:5310)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4568)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4461)
at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:1962)
at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1371)
at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1334)
at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:563)
at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:2847)
at android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:3145)
at android.view.View.layout(View.java:13754)
at android.view.ViewGroup.layout(ViewGroup.java:4362)
at android.support.v4.view.ViewPager.onLayout(ViewPager.java:1627)
at android.view.View.layout(View.java:13754)
at android.view.ViewGroup.layout(ViewGroup.java:4362)
at android.support.design.widget.CoordinatorLayout.layoutChild(CoordinatorLayout.java:1034)
at android.support.design.widget.CoordinatorLayout.onLayoutChild(CoordinatorLayout.java:744)
at android.support.design.widget.ViewOffsetBehavior.onLayoutChild(ViewOffsetBehavior.java:42)
at android.support.design.widget.AppBarLayout$ScrollingViewBehavior.onLayoutChild(AppBarLayout.java:1180)
at android.support.design.widget.CoordinatorLayout.onLayout(CoordinatorLayout.java:757)
at android.view.View.layout(View.java:13754)
at android.view.ViewGroup.layout(ViewGroup.java:4362)
at android.widget.FrameLayout.onLayout(FrameLayout.java:448)
at android.view.View.layout(View.java:13754)
at android.view.ViewGroup.layout(ViewGroup.java:4362)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1649)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1507)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1420)
at android.view.View.layout(View.java:13754)
at android.view.ViewGroup.layout(ViewGroup.java:4362)
at android.widget.FrameLayout.onLayout(FrameLayout.java:448)
at android.view.View.layout(View.java:13754)
at android.view.ViewGroup.layout(ViewGroup.java:4362)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1649)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1507)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1420)
at android.view.View.layout(View.java:13754)
at android.view.ViewGroup.layout(ViewGroup.java:4362)
at android.widget.FrameLayout.onLayout(FrameLayout.java:448)
at android.view.View.layout(View.java:13754)
at android.view.ViewGroup.layout(ViewGroup.java:4362)
at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:1866)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1687)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:998)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:4212)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:725)
at android.view.Choreographer.doCallbacks(Choreographer.java:555)
at android.view.Choreographer.doFrame(Choreographer.java:525)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:711)
at android.os.Handler.handleCallback(Handler.java:615)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4745)
at java.lang.reflect.Method.invokeNative(Native Method)
Do you guys know any idea what is wrong with my code? Thanks.
First thing that I noticed is that you aren't removing the sticky in your onReturnResults(List<Result> results)
method ... not sure if that is on purpose or not ... but thought it should be mentioned.
The main point that I wanted to stress is with regards to having two onEvent() methods leveraging the same generic class List<>
- this might very well be the issue - a small code change and quick test can verify this
Create a class
for each List<>
public class Statuses
{
List<Status> list;
public Statuses(List<Status> data) { list = data; }
}
public class Results
{
List<Result> list;
public Results(List<Result> data) { list = data; }
}
Update your onEvent() method signatures:
public void onReturnList(Statuses statuses)
public void onReturnResults(Results results)
Update your .postSticky() method calls:
eventBus.postSticky(new Statuses(statuses));
eventBus.postSticky(new Results(results));
Of course, you'll need to access the Lists from their class member (for example):
foreach (var status in statuses.list)
and
foreach (var result in results.list)
If the problem you're seeing simply goes away after these changes are made - then it would make sense to assume that greenrobot's EventBus doesn't take into account the type contained within the generic List class during it's reflection calls seen in the callstack. It might simply look for the first matching signature that contains a List argument; and when there are 2 or more matches, the right one just might not get called.
This is guesswork; so you'll have to try it out and see if it helps -- but I've had success using greenrobot's EventBus in a project using this type of implementation when I need List<>s of classes to avoid ambiguity.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With