Webview crash after fragment tab change - android-fragments

I have a activity with 3 actionbar tabs. Each tab contains a webview which loads a URL at Fragment oncreate(). Everything is working fine but if i switch tabs quickly the onpagefinished appears after the tab change so when the calling fragment is gone, resulting in an NullPointerException. Is there a way to prevent this?
I tried in my fragment:
public void onDestroy() {
super.onDestroy();
try {
myWebView.stopLoading();
} catch (Exception e) {
}
try {
myWebView.clearView();
} catch (Exception e) {
}
and in my tab listener:
onTabSelected(Tab tab, FragmentTransaction ft) {
// StartActivity.mViewPager.setCurrentItem(tab.getPosition());
if (FinishedLoading == true){
ft.replace(R.id.fragment_container, fragment);
}
}
Both options don't prevent the APP to crash.
The error i recieve:
java.lang.NullPointerException
at com.***.Fragment1$MyWebViewClient.onPageFinished(Fragment1.java:233)
at android.webkit.CallbackProxy.handleMessage(CallbackProxy.java:389)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4898)
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:1006)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:773)
at dalvik.system.NativeStart.main(Native Method)

I was facing this issue as well. If you haven't solved it, maybe you would like to try implementing onPause in your fragment like this:
#Override
public void onPause() {
if (webview.isShown() == false) {
webview.stopLoading();
}
super.onPause();
}
#Override
public void onResume() {
super.onResume();
}
Where webview is your webview

Related

JavaFX many task work in GUI

I ran a thread that updates the open time of the application. It works well. I've expanded the Service class. The time from this task update my GUI, textField by Platform.runLater
#Override
protected Task<Void> createTask() {
return new Task<Void>() {
#Override
protected Void call() throws Exception {
while (!isCancelled()) {
if (isPause == false) {
try {
Platform.runLater(() -> {
currentTimeInApp = currentTimeInApp + 1;
upPanelController.timeInApp.setText
(currentTimeInApp.toString());
}
});
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
if (isCancelled())
break;
}
}
return null;
}
};
}
I would like to run a second thread which also updates GUI. I can't run the same thread. Can two independent threads be updated GUI ?
Most of the information on the internet is dedicated to one topic. Thank you for every suggestion
Yes, you can use as many threads as you like. You just have to make sure that you always do the GUI update via Platform.runLater.

FAN Native ads refresh:java.lang.OutOfMemoryError: pthread_create (1040KB stack) failed: Try again

I met a OOM-issue of FAN native ads with the latest version 4.28.0.I want the FAN native ads refresh every 10 seconds,so I create a new instance of NativeAd and load ad every 10s.Implemented as the official docs says. I reproduced this issue in official demo too.To reproduce easily,I changed the interval time from 10s to 2s. here is the sample code of my test:
private void showNativeAd() {
nativeAd = new NativeAd(getContext(), mAdunit);
nativeAd.setAdListener(new AdListener() {
#Override
public void onError(Ad ad, AdError error) {
// Ad error callback
Log.e(TAG,"failed-->" + error.getErrorMessage());
//refresh after 2s
requestDelay(2000);
}
#Override
public void onAdLoaded(Ad ad) {
Log.e(TAG,"loaded-->");
// Add the Ad view into the ad container.
//...
//refresh after 2s
requestDelay(2000);
}
#Override
public void onAdClicked(Ad ad) {
// Ad clicked callback
}
#Override
public void onLoggingImpression(Ad ad) {
// On logging impression callback
}
});
// Request an ad
nativeAd.loadAd();
}
private void requestDelay(int millseconds){
if (handler == null){
handler = new Handler(Looper.getMainLooper());
}
handler.postDelayed(new Runnable() {
#Override
public void run() {
showNativeAd();
}
},millseconds);
}
It is running well at the beginning, but about an hour later,crashed.here is the crash log:
java.lang.OutOfMemoryError: pthread_create (1040KB stack) failed: Try again
at java.lang.Thread.nativeCreate(Native Method)
at java.lang.Thread.start(Thread.java:1063)
at java.util.concurrent.ThreadPoolExecutor.addWorker(ThreadPoolExecutor.java:920)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1327)
at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:590)
at com.facebook.ads.internal.m.b$1.run(Unknown Source)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:6145)
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:1399)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)
Can anyone help me?
this issue seems be fixed in the latest version v4.28.1.

Calling Fragment from RecyclerView Adapter

I have a recyclerView that shows a list in cardView. This recyclerview is located in one fragment that shown in a viewPager tab. I want to go to new Fragment when thumbnail in cardview is clicked.
I implemented following onBindViewHolder in order to have this functionality:
holder.thumbnail.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Fragment productDetailFragment = new ProductDetailFragment();
(FragmentActivity)mContext).getSupportFragmentManager().beginTransaction()
.replace(R.id.grid_page_recycler_view, productDetailFragment).commit();
}
});
But after running, it returns:
E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.NullPointerException
at android.support.v7.widget.RecyclerView.findMinMaxChildLayoutPositions(RecyclerView.java:3757)
at android.support.v7.widget.RecyclerView.dispatchLayoutStep1(RecyclerView.java:3494)
at android.support.v7.widget.RecyclerView.onMeasure(RecyclerView.java:3019)
at android.view.View.measure(View.java:15819)
at android.widget.RelativeLayout.measureChild(RelativeLayout.java:666)
at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:477)
at android.view.View.measure(View.java:15819)
at android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1658)
at android.view.View.measure(View.java:15819)
at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:681)
at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:461)
at android.view.View.measure(View.java:15819)
at android.support.v4.widget.DrawerLayout.onMeasure(DrawerLayout.java:1081)
at android.view.View.measure(View.java:15819)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4890)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
at android.view.View.measure(View.java:15819)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4890)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1404)
at android.widget.LinearLayout.measureVertical(LinearLayout.java:695)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:588)
at android.view.View.measure(View.java:15819)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4890)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2176)
at android.view.View.measure(View.java:15819)
at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:1965)
at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1146)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1356)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1046)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:4603)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:749)
at android.view.Choreographer.doCallbacks(Choreographer.java:562)
at android.view.Choreographer.doFrame(Choreographer.java:532)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:735)
at android.os.Handler.handleCallback(Handler.java:725)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5086)
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:793)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
at dalvik.system.NativeStart.main(Native Method)
What's the reason? It's notable that if I want to call another activity, it is easy to implement.
Thanks.
And I must say that there are several similar questions here, but I could not use them.
Create one method for replacing fragment in your MAinActivity.
Take ViewPager in a Fragment and push it from MainActivity.
Now Call replace fragment method in your recyclerView Adapter.
public void replaceFragment(Fragment fragment) {
String backStateName = fragment.getClass().getName();
FragmentManager manager = getSupportFragmentManager();
boolean fragmentPopped = manager.popBackStackImmediate(backStateName, 0);
if (!fragmentPopped && manager.findFragmentByTag(backStateName) == null) {
FragmentTransaction ft = manager.beginTransaction();
ft.replace(R.id.frame_container, fragment, backStateName);
ft.addToBackStack(backStateName);
ft.commit();
}
}

rxjava, retrofit how to retry(retryWhen) understand specific situation?

I have a function which connect server and login account:
Observabe<Response> loginAccount();
Most of the time, it can login success:
loginAccount().subscribe(new Subscriber<Response>() {
#Override
public void onCompleted() {
System.out.println("success");
}
#Override
public void onError(Throwable e) {
e.printStackTrace();
}
#Override
public void onNext(Response authenticationResponseResult) {
System.out.println(authenticationResponseResult,toString());
}
});
However, there are serveral times there is an SocketTimeoutException.
I only want to retry on SocketTimeoutException and at most retry twice.
How can I implement?
I know probably I can use retryWhen, but I don't know how to use it only when the exception is SocketTimeoutException and how to retry at most twice.
Use the 2-parameter overload of retry:
loginAccount()
.retry((throwable, count) -> count < 2 && (throwable instanceof SocketTimeoutException))
.subscribe(....);

Vaadin button setEnabled(false) doesn't enable

Vaadin newbie: When a user presses a button, I like to disable it so he knows that he clicked it and there's some work going on in the background. When the (long) task is completed, I'd like to enable the button.
For this, I'm using 2 threads (background and work) but for some reason the button doesn't enabled at the end of the task.
In other words, once clicked it goes to enabled(false) and never coming back. Why? and how can I fix it?
button.addClickListener(new ClickListener()
{
public void buttonClick(ClickEvent event)
{
Thread background = new Thread(new Runnable(){
#Override
public void run()
{
Thread work = new Thread(new Runnable(){
#Override
public void run()
{
button.setEnabled(false);
try
{
Thread.sleep(2000); //long work here!
} catch (InterruptedException e)
{
e.printStackTrace();
}
button.setEnabled(true); //doesn't enable at the end of the long work!
}});
work.start();
try
{
work.join();
} catch (InterruptedException e)
{
e.printStackTrace();
}
}});
background.start();
}
});
Maybe the best approach would be to use Button.setDisableOnClick(true) for the button and do the processing directly in the event handler without a background thread. This will show the standard loading indicator to the user until processing is done.
Otherwise you need to enable server push (#Push) and remember to use UI.access() in the background thread before updating the UI. See https://vaadin.com/book/-/page/advanced.push.html

Resources