How can I implement in fragment with my interface in another fragment - java

I created a interface in a fragment like following:
public interface SGFCallBackInterface {
void itemSelected(Item item);
}
private SGFCallBackInterface mCallbackInterface;
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof SGFCallBackInterface) {
mCallbackInterface = (SGFCallBackInterface) context;
} else {
throw new RuntimeException(context.toString() + " must implement SelectGdsFragment.SGFCallBackInterface");
}
}
public void setSGFCallBackInterface(SGFCallBackInterface mCallbackInterface) {
this.mCallbackInterface = mCallbackInterface;
}
and I would implement that in another fragment like the following
public class SaleMenageFragment extends Fragment implements SelectGdsFragment.SGFCallBackInterface {
...
SelectGdsFragment selectGdsFragment = new SelectGdsFragment();
selectGdsFragment.setSGFCallBackInterface(SaleMenageFragment.this);
...
}
#Override
public void onItemSelected(Item item) {
...
}
But it's still not working, this is the error log:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.leo.test, PID: 3853
java.lang.RuntimeException: com.leo.test.Control.IndexActivity#2a66aece must implement SelectGdsFragment.SGFCallBackInterface
at com.leo.test.Control.Fragment.SaleManagement.SelectGdsClsFragment.onAttach(SelectGdsFragment.java:42)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1019)
at android.support.v4.app.BackStackRecord.setLastIn(BackStackRecord.java:779)
at android.support.v4.app.BackStackRecord.calculateFragments(BackStackRecord.java:819)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:660)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1617)
at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:517)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
I think the error log means my IndexActivity is not implementing SelectGdsFragment.SGFCallBackInterface.
But I don't want to implement that in IndexActivity.
I want to implement that in SaleMenageFragment.
How can I do that?

I am afraid you have to implement it in your Activity
See the doc
Communicating with Fragments
Hope it helps!

Just remove the part in onAttach(Context context) method like this:
public interface SGFCallBackInterface {
void itemSelected(Item item);
}
private SGFCallBackInterface mCallbackInterface;
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof SGFCallBackInterface) {
mCallbackInterface = (SGFCallBackInterface) context;
} // this wont throw an exception if the activity does not implement that interface
}
public void setSGFCallBackInterface(SGFCallBackInterface mCallbackInterface) {
this.mCallbackInterface = mCallbackInterface;
}

Related

Retrofit2 java null pointer object reference

Hi I am trying to parse JSON using Retrofit, save it on Sqlite and display on RecyclerView. However my app crashes when I try to open the activity.
Below is my full codes of related activity. Could you please help me with resolving the issue?
Thank you
public class InventoryProductActivity extends AppCompatActivity implements InventoryProductListAdapter.CustomClickListener {
private static final String TAG = InventoryProductActivity.class.getSimpleName();
private InventoryProductListAdapter mInventoryProductListAdapter;
private RecyclerView mRecyclerView;
private RetrofitClient mRetrofitClient;
LinearLayoutManager mLinearLayoutManager;
private WarehouseDatabase mDatabase;
private ProgressDialog mProgressDialog;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_inventory_product);
configViews();
mRetrofitClient = new RetrofitClient();
mDatabase = new WarehouseDatabase(this);
loadInventoryProductFeed();
}
private void configViews() {
mRecyclerView = findViewById(R.id.recycler_view_inventory_product);
mRecyclerView.setHasFixedSize(true);
mLinearLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLinearLayoutManager);
mInventoryProductListAdapter = new InventoryProductListAdapter(this);
mRecyclerView.setAdapter(mInventoryProductListAdapter);
}
private void loadInventoryProductFeed() {
mProgressDialog = new ProgressDialog(InventoryProductActivity.this);
mProgressDialog.setMessage("Loading Inventory Data...");
mProgressDialog.setCancelable(true);
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
mProgressDialog.setIndeterminate(true);
mProgressDialog.show();
mInventoryProductListAdapter.reset();
if (getNetworkAvailability()) {
getFeed();
} else {
getFeedFromDatabase();
}
}
private void getFeed() {
Call<List<InventoryProductModel>> listCall = mRetrofitClient.getWarehouseServiceInventoryProduct().getAllInventoryProducts();
listCall.enqueue(new Callback<List<InventoryProductModel>>() {
#Override
public void onResponse(Call<List<InventoryProductModel>> call, Response<List<InventoryProductModel>> response) {
if (response.isSuccessful()) {
List<InventoryProductModel> inventoryProductModelList = response.body();
for (int i = 0; i < inventoryProductModelList.size(); i++) {
InventoryProductModel inventoryProductModel = inventoryProductModelList.get(i);
mInventoryProductListAdapter.notifyDataSetChanged();
}
} else {
int sc = response.code();
switch (sc) {
}
}
mProgressDialog.dismiss();
}
#Override
public void onFailure(Call<List<InventoryProductModel>> call, Throwable t) {
mProgressDialog.dismiss();
Toast.makeText(getApplicationContext(), t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
private void getFeedFromDatabase() {
List<InventoryProductModel> inventoryProductModelList = mDatabase.getInventoryProducts();
for (int i = 0; i < inventoryProductModelList.size(); i++) {
InventoryProductModel inventoryProductModel = inventoryProductModelList.get(i);
Log.d(TAG, inventoryProductModel.getName() + "||" + inventoryProductModel.getCountryId());
}
mProgressDialog.dismiss();
}
private boolean getNetworkAvailability() {
return Utils.isNetworkAvailable(getApplicationContext());
}
#Override
public void onClick(int position) {
}
}
E/WindowManager: android.view.WindowLeaked: Activity
codes.bala.bmsfinal1.activity.MainActivity has leaked window
DecorView#52c3fcd[] that was originally added here
at android.view.ViewRootImpl.(ViewRootImpl.java:418)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:331)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:93)
at android.app.Dialog.show(Dialog.java:322)
at android.app.ProgressDialog.show(ProgressDialog.java:116)
at android.app.ProgressDialog.show(ProgressDialog.java:104)
at codes.bala.bmsfinal1.activity.MainActivity.login(MainActivity.java:61)
at codes.bala.bmsfinal1.activity.MainActivity$1.onClick(MainActivity.java:41)
at android.view.View.performClick(View.java:5637)
at android.view.View$PerformClick.run(View.java:22429)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6119)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
I/ViewConfigCompat: Could not find method getScaledScrollFactor() on
ViewConfiguration D/AndroidRuntime: Shutting down VM
--------- beginning of crash E/AndroidRuntime: FATAL EXCEPTION: main
Process: codes.bala.bmsfinal1, PID: 12077
java.lang.RuntimeException: Unable to start activity ComponentInfo{codes.bala.bmsfinal1/codes.bala.bmsfinal1.activity.InventoryProductActivity}:
java.lang.NullPointerException: Attempt to invoke interface method
'retrofit2.Call
codes.bala.bmsfinal1.iinterface.WarehouseService.getAllInventoryProducts()'
on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2665)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6119)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
Caused by: java.lang.NullPointerException: Attempt to invoke interface
method 'retrofit2.Call
codes.bala.bmsfinal1.iinterface.WarehouseService.getAllInventoryProducts()'
on a null object reference
at codes.bala.bmsfinal1.activity.InventoryProductActivity.getFeed(InventoryProductActivity.java:88)
at codes.bala.bmsfinal1.activity.InventoryProductActivity.loadInventoryProductFeed(InventoryProductActivity.java:70)
at codes.bala.bmsfinal1.activity.InventoryProductActivity.onCreate(InventoryProductActivity.java:46)
at android.app.Activity.performCreate(Activity.java:6679)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2618)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726) 
at android.app.ActivityThread.-wrap12(ActivityThread.java) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477) 
at android.os.Handler.dispatchMessage(Handler.java:102) 
at android.os.Looper.loop(Looper.java:154) 
at android.app.ActivityThread.main(ActivityThread.java:6119) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776) 
Application terminated.
getWarehouseServiceInventoryProduct()
method return null.
You should set breakpoint inside this method and check what happening (or add some logs to this method).

Call Interface function from main class from sub object

Solution:
The following worked fine, but I had two Activities already using my helper class, but forgot to add the Interface to one Activity.
So I got the TypeCastException.
But I did not realize I always looked at the wrong Activity, so I could not find the issue.
I currently write my first android service, which works fine.
Now I realized, that I have to bind unbind, check binding all over and so I thought to put all into a subclass and only do an interface with callbacks for the only functions I need.
But now i am stuck to call my interface functions
onTcBlueServiceConnected()
onTcBlueServiceDisconnected()
I simply want to prevent to write the same code over and over again.
Each activity I have to use the service, I extend from this helper class, instead of the AppCompatActivity.
Maybe I chose the wrong path, but lost with the right words for a search.
As far as I understand bound services, I have to bind from each activity I access the service, and unbind of course when it is destroyed.
So I thought this is a good approach
public abstract class TcBlueServiceHelper extends AppCompatActivity {
private static String LOG_TAG = "TcBlueServiceHelper";
TcBlueService mTcBlueService;
TcBlueService.TcBlueBinder myBinder;
boolean mServiceBound = false;
Context mCallingContext;
public TcBlueServiceHelper(Context callingContext) {
mCallingContext = callingContext;
}
public TcBlueServiceHelper(){
mCallingContext = this;
}
public void bindServiceSave(){
if (mServiceBound == false) {
Intent intent = new Intent(this, TcBlueService.class);
startService(intent);
bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
}
}
public void unbindServiceSave(){
if (mServiceBound) {
unbindService(mServiceConnection);
mServiceBound = false;
}
}
public TcBlueService.TcBlueBinder getBinder(){
return myBinder;
}
private ServiceConnection mServiceConnection = new ServiceConnection() {
#Override
public void onServiceDisconnected(ComponentName name) {
mServiceBound = false;
((ITcBlueServiceHelper)mCallingContext).onTCBServiceDisconnected(name);
}
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
myBinder = (TcBlueService.TcBlueBinder) service;
mTcBlueService = myBinder.getService();
mServiceBound = true;
((ITcBlueServiceHelper)mCallingContext).onTCBServiceConnected(name, service);
}
};
public interface ITcBlueServiceHelper{
public void onTCBServiceConnected(ComponentName name, IBinder service);
public void onTCBServiceDisconnected(ComponentName name);
}
}
My first thought to cast result in a "ClassCastException"
E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.ClassCastException: de.mobacomp.android.freightweight.StartActivity cannot be cast to de.mobacomp.android.freightweight.TcBlueServiceHelper$ITcBlueServiceHelper
at de.mobacomp.android.freightweight.TcBlueServiceHelper$1.onServiceConnected(TcBlueServiceHelper.java:72)
at android.app.LoadedApk$ServiceDispatcher.doConnected(LoadedApk.java:1068)
at android.app.LoadedApk$ServiceDispatcher$RunConnection.run(LoadedApk.java:1085)
at android.os.Handler.handleCallback(Handler.java:605)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4424)
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:784)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
at dalvik.system.NativeStart.main(Native Method)

How to initialize menu library in Android

I want use this library for menu in my Application : GuillotineMenu-Android.
For close menu with onBackPress button i use this code :
#Override
public void onBackPressed() {
if (!isOpened) {
super.onBackPressed();
}
mGuillotineAnimation.close();
}
and set this codes to builder :
.setGuillotineListener(new GuillotineListener() {
#Override
public void onGuillotineOpened() {
isOpened = true;
}
#Override
public void onGuillotineClosed() {
isOpened = false;
}
})
Builder full code:
View guillotineMenu = LayoutInflater.from(this).inflate(R.layout.menu_layout, null);
root.addView(guillotineMenu);
toolbar_menuImage = (ImageView) toolbar.findViewById(R.id.toolbar_pages_logo);
new GuillotineAnimation.GuillotineBuilder(guillotineMenu, guillotineMenu.findViewById(R.id.menu_layout_image), toolbar_menuImage)
.setStartDelay(RIPPLE_DURATION)
.setActionBarViewForAnimation(toolbar)
.setClosedOnStart(true)
.setGuillotineListener(new GuillotineListener() {
#Override
public void onGuillotineOpened() {
isOpened = true;
}
#Override
public void onGuillotineClosed() {
isOpened = false;
}
})
.build();
and write this code above of onCreate() method :
private GuillotineAnimation mGuillotineAnimation;
private boolean isOpened = true;
but when running application, and click onBackPress button show me this error :
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.app, PID: 28891
java.lang.NullPointerException: Attempt to invoke virtual method 'void com.example.app.Components.SlidingMenu.animation.GuillotineAnimation.close()' on a null object reference
at com.example.app.Activities.Category_page.onBackPressed(Category_page.java:256)
at android.app.Activity.onKeyUp(Activity.java:2506)
at android.view.KeyEvent.dispatch(KeyEvent.java:2633)
at android.app.Activity.dispatchKeyEvent(Activity.java:2757)
at android.support.v7.app.AppCompatActivity.dispatchKeyEvent(AppCompatActivity.java:543)
at android.support.v7.view.WindowCallbackWrapper.dispatchKeyEvent(WindowCallbackWrapper.java:53)
at android.support.v7.app.AppCompatDelegateImplBase$AppCompatWindowCallbackBase.dispatchKeyEvent(AppCompatDelegateImplBase.java:312)
at android.support.v7.view.WindowCallbackWrapper.dispatchKeyEvent(WindowCallbackWrapper.java:53)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:2297)
at android.view.ViewRootImpl$ViewPostImeInputStage.processKeyEvent(ViewRootImpl.java:3995)
at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:3957)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3488)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3541)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3507)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3515)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3488)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3541)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3507)
at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3617)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3515)
at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3674)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3488)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3541)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3507)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3515)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3488)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3541)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3507)
at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3650)
at android.view.ViewRootImpl$ImeInputStage.onFinishedInputEvent(ViewRootImpl.java:3811)
at android.view.inputmethod.InputMethodManager$PendingEvent.run(InputMethodManager.java:2242)
at android.view.inputmethod.InputMethodManager.invokeFinishedInputEventCallback(InputMethodManager.java:1883)
at android.view.inputmethod.InputMethodManager.finishedInputEvent(InputMethodManager.java:1874)
at android.view.inputmethod.InputMethodManager$ImeInputEventSender.onInputEventFinished(InputMethodManager.java:2219)
at android.view.InputEventSender.dispatchInputEventFinished(InputEventSender.java:141)
at android.os.MessageQueue.nativePollOnce(Native Method)
at android.os.MessageQueue.next(MessageQueue.java:143)
at android.os.Looper.loop(Looper.java:122)
at android.app.ActivityThread.main(ActivityThread.java:5349)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:908)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:703)
I think i should Initialize mGuillotineAnimation in onCreate() method, but how can i initialize this?
Thanks all <3
You forgot to instanciate mGuillotineAnimation :
mGuillotineAnimation = new GuillotineAnimation.GuillotineBuilder(guillotineMenu, guillotineMenu.findViewById(R.id.menu_layout_image), toolbar_menuImage)
.setStartDelay(RIPPLE_DURATION)
.setActionBarViewForAnimation(toolbar)
.setClosedOnStart(true)
.setGuillotineListener(new GuillotineListener() {
#Override
public void onGuillotineOpened() {
isOpened = true;
}
#Override
public void onGuillotineClosed() {
isOpened = false;
}
})
.build();

Fatal exception while starting activity using intent (null pointer exception)

The following piece of code is throwing a null pointer exception in my application.Im trying to invoke an activity through an intent, (some background info on this is that the activity being opened is triggered through the click of a button, thus I have called the startActivity() function in the button's onclickListener itself.
Here's the code:
public class CategoryButtonOnClickListener extends Activity implements View.OnClickListener {
private final int position;
public CategoriesPage categoriesPage;
Context context;
public CategoryButtonOnClickListener(int position, Context contextPassed) {
this.position = position;
this.context = contextPassed;
categoriesPage = new CategoriesPage();
}
public void onClick(View v) {
callCategoryList(this.position);
}
public void callCategoryList(int position) {
String[] categories = categoriesPage.getCategories();
Intent categoriesList = new Intent(this.context,BooksWithCategories.class);
//I tried commenting this code to fix it as seen from another post, didnt work
//categoriesList.putExtra("Category:",categories[position]);
startActivity(categoriesList);
//Toast.makeText(context,categories[position],Toast.LENGTH_LONG).show();
}
}
The error thrown is as follows:
1-17 23:27:15.076 2614-2614/com.dogra.booker E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.dogra.booker, PID: 2614
java.lang.NullPointerException: Attempt to invoke virtual method 'android.app.ActivityThread$ApplicationThread android.app.ActivityThread.getApplicationThread()' on a null object reference
at android.app.Activity.startActivityForResult(Activity.java:3736)
at android.app.Activity.startActivityForResult(Activity.java:3697)
at android.app.Activity.startActivity(Activity.java:4007)
at android.app.Activity.startActivity(Activity.java:3975)
at com.dogra.booker.UI.Model.CategoryButtonOnClickListener.callCategoryList(CategoryButtonOnClickListener.java:36)
at com.dogra.booker.UI.Model.CategoryButtonOnClickListener.onClick(CategoryButtonOnClickListener.java:29)
at android.view.View.performClick(View.java:4756)
at android.view.View$PerformClick.run(View.java:19749)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5221)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
Any suggestions on what could be the problem are appreciated.
Place this method in your code :
Activity getAct() {
Context context = getContext();
while (context instanceof ContextWrapper) {
if (context instanceof Activity) {
return (Activity) context;
}
context = ((ContextWrapper) context).getBaseContext();
}
return null;
}
and then use it for starting the activity:
Intent categoriesList = new Intent(getAct(),BooksWithCategories.class);
can try this
Intent categoriesList = new Intent(CategoryButtonOnClickListener.this,BooksWithCategories.class);

FragmentTransaction in WebViewClient.shouldOverrideUrlLoading throws IllegalStateException

I seem to be fighting with a race condition, the cause of which I can't seem to pin down. When executing the below code, I intermittently get the stack trace below.
Is there some obvious rule of the Fragment lifecycle I am disobeying? I am not clear on what would explicitly forbid me from performing a transaction here to handle the event.
I am using a WebViewClient to detect external URLs clicked within a local .html document - as in, URLs which point to a non-local host. I am using Otto's EventBus to post those actions to an Activity. When the Activity receives those events, I want to show those external URLs in a different Fragment, by calling FragmentTransaction.replace()
DefaultWebViewClient.java
#Override
public boolean shouldOverrideUrlLoading(final WebView view, final String url) {
boolean shouldOverride;
if (urlIsLocal(url)) {
shouldOverride = super.shouldOverrideUrlLoading(view, url);
} else {
// trigger an event for the fragment to swap out
// return true to tell the webview not to load it...
EventBus.getInstance().post(new LoadExternalUrlEvent(url));
shouldOverride = true;
}
return shouldOverride;
}
FragmentActivity.java
#Subscribe
public void onLoadExternalUrlEvent(LoadExternalUrlEvent externalLoadEvent) {
final BrowserFragment browserFragment = new BrowserFragment();
Bundle args = new Bundle();
args.putSerializable(BrowserFragment.ARG_LOAD_EXTERNAL_URL_EVENT, externalLoadEvent);
browserFragment.setArguments(args);
getSupportFragmentManager().beginTransaction()
.replace(R.id.fragment_container, browserFragment, BrowserFragment.FRAGMENT_TAG)
.addToBackStack(null).commit();
}
LoadExternalUrlEvent.java
public class LoadExternalUrlEvent implements Serializable {
private static final long serialVersionUID = 1L;
public final String url;
public LoadExternalUrlEvent(String url) {
this.url = url;
}
#Override
public String toString() {
return "LoadExternalUrlEvent [url=" + url + "]";
}
}
EventBus.java
import com.squareup.otto.Bus;
public class EventBus {
private static Bus _INSTANCE;
public static synchronized Bus getInstance() {
if (null == _INSTANCE) {
_INSTANCE = new Bus();
}
return _INSTANCE;
}
}
Stack trace
java.lang.RuntimeException: Could not dispatch event: class <omitted>.LoadExternalUrlEvent to handler [EventHandler public void <omitted>Activity.onLoadExternalUrlEvent(<omitted>LoadExternalUrlEvent)]: Can not perform this action after onSaveInstanceState
at com.squareup.otto.Bus.throwRuntimeException(Bus.java:456)
at com.squareup.otto.Bus.dispatch(Bus.java:386)
at com.squareup.otto.Bus.dispatchQueuedEvents(Bus.java:367)
at com.squareup.otto.Bus.post(Bus.java:336)
at <omitted>DefaultWebViewClient.shouldOverrideUrlLoading(DefaultWebViewClient.java:51)
at com.android.webview.chromium.WebViewContentsClientAdapter.shouldOverrideUrlLoading(WebViewContentsClientAdapter.java:293)
at com.android.org.chromium.android_webview.AwContentsClientBridge.shouldOverrideUrlLoading(AwContentsClientBridge.java:96)
at com.android.org.chromium.base.SystemMessageHandler.nativeDoRunLoopOnce(Native Method)
at com.android.org.chromium.base.SystemMessageHandler.handleMessage(SystemMessageHandler.java:27)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:157)
at android.app.ActivityThread.main(ActivityThread.java:5356)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1265)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1360)
at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1378)
at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:595)
at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:574)
at <omitted>Activity.run(<omitted>Activity.java:162)
at <omitted>Activity.onLoadExternalUrlEvent(<omitted>Activity.java:156)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.squareup.otto.EventHandler.handleEvent(EventHandler.java:89)
at com.squareup.otto.Bus.dispatch(Bus.java:384)
... 15 more
A/libc(2689): Fatal signal 6 (SIGABRT) at 0x00000a81 (code=-6), thread 2689
I discovered the problem.
Because I was calling EventBus.register() in Activity.onCreate() I was getting multiple instances of the Activity on my backstack which would act as responders to these events.
The solution is to either register your Activity as late as possible with
#Override
protected void onResume() {
super.onResume();
EventBus.getInstance().register(this);
}
#Override
protected void onPause() {
EventBus.getInstance().unregister(this);
super.onPause();
}
or to declare your Activity as a single instance with
android:launchMode="singleTask"

Categories

Resources