Salvare lo stato di una WebView in un layout “Tabs + Swipe” con ViewPager e FragmentPagerAdapter

Nell’articolo Tabs e swipe views Szymon chiede come implementare una WebView in modo da conservare il suo stato nel passare da una tab all’altra in modo simile a come spiegato in Come salvare lo stato di una WebView in un Fragment di una Action Bar.

Partendo dal codice in Tabs e swipe views

  1. aggiungi un permesso per accedere a internet in AndroidManifest.xml
  2. sostituisci il file res/layout/tab3.xml

    dove aggiungo una WebView nella terza tab;
    come potrai verificare questa WebView conserva comunque il proprio stato nel passare da una tab contigua (dalla seconda tab in questo caso) senza la necessità di codice per ripristinare lo stato della WebView, invece la WebView è resettata nel passare da una tab non contigua (dalla prima tab in questo caso);
  3. sostituisci il file eu/lucazanini/viewpager/MainActivity.java

    nella classe interna statica TabFragment:

    • nel metodo onCreate inizializzo il Bundle webViewBundle in cui salvo lo stato della WebView
    • nel metodo onCreateView a partire dalla riga 207 inizializzo WebView e se esiste webViewBundle non nullo ripristino la WebView
    • nel metodo onPause salvo lo stato della WebView nel Bundle webViewBundle

    commentando le righe 211-216 puoi verificare quanto ho scritto prima e cioè che il frammento non è distrutto passando da una tab a un’altra tab contigua e quindi anche lo stato della WebView è conservato;
    questo è il comportamento di default per ViewPager che conserva in memoria la tab selezionata e le due adiacenti;
    il codice nelle righe 211-216 e nel metodo onPause serve per ripristinare lo stato della WebView nel caso si selezioni la terza tab provenendo dalla prima tab.

Nel passare alla terza tab provenendo dalla prima, lo stato della WebView è ripristinato ma la WebView è anche ricaricata a differenza di quanto accade nel passare dalla seconda tab alla terza tab in cui l’intero frammento è salvato in memoria (puoi dedurre questo anche dai differenti tempi di caricamento della terza tab a seconda se si proviene dalla prima o dalla seconda tab).
E’ possibile modificare il numero delle tab salvate in memoria da ViewPager con il metodo setOffscreenPageLimit il cui argomento indica il numero di pagine (tab) prima e dopo la corrente pagina da tenere in memoria.

Considera il seguente codice per eu/lucazanini/viewpager/MainActivity.java

Il punto chiave è la riga 81 che imposta a 2 il numero di pagine da tenere in memoria prima e dopo quella corrente, e nel caso di tre tab come in questo esempio significa che tutte le pagine sono in memoria.
Ora lo stato delle WebView è conservato senza la necessità di utilizzare un Bundle per salvare e ripristinare lo stato perchè tutti i fragment sono conservati in memoria.

Referenze:
ViewPager

19 risposte a “Salvare lo stato di una WebView in un layout “Tabs + Swipe” con ViewPager e FragmentPagerAdapter”

  1. Hi Luca,
    One question: Is this compatible with android versions older than 3.0 ?
    Following your tutorials it’s working great on android 4.1 and 4.2 but when i tried it on android 2.3.6 i’m getting:
    java.lang.ClassNotFoundException in dalvik.system.PathClassLoader.findClass
    that exception is thrown at the moment I execute the app.

    I tried installing latest compatibility package because I tought actionbar was not supported. I changed my mainclass from FragmentActivity to ActionBarActivity and set theme to compattheme and it’s working on 4.1 and 4.2 but in android 2.3.6 i’m having the same problem again.
    Any suggestions or workarounds?
    Thanks !

  2. Hi, first i want to say thanks, this is working GREAT.
    The comments in code make it completely clear.
    But i have one issue and maybe you can help me :
    I managed to put 3 webviews in 3 fragments but whenever i rotate the screen , the webviews gets reloaded.
    This is usually solved by overriding on configurationchange and saving the state of the webview but I cannot do that with 3 webviews at the same time, or at least i dont know how. Do you have any idea on how to do that?
    Thanks for your time

      1. Oohh, i read that article before and tried out but it didn’t work, now i realize I made a a mistake when I wrote the manifest.
        It’s working great, can’t believe it was so easy haha.
        Thanks a lot from Argentina! keep this site up, it’s great !

      1. Same question here?
        all tabs loads the same webpage.. how to change this code so each can have a diferent webpage

        /**
        * A fragment that launches other parts of the demo application.
        */
        public static class TabFragment extends Fragment {

        public static final String ARG_OBJECT = “object”;

        private WebView webView;

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {

        Bundle args = getArguments();
        int position = args.getInt(ARG_OBJECT);

        int tabLayout = 0;
        switch (position) {
        case 0:
        tabLayout = R.layout.auto;
        break;
        case 1:
        tabLayout = R.layout.fragment_main;
        break;
        case 2:
        tabLayout = R.layout.fragment_main;
        break;
        }

        View rootView = inflater.inflate(tabLayout, container, false);

        webView = (WebView) rootView.findViewById(R.id.browser);
        if (webView != null) {
        webView.setWebViewClient(new WebViewClient());
        webView.loadUrl(“http://www.headgone.net”);
        }

        return rootView;

        }
        }

  3. Hello, thank you for the help but I have a question

    When I open a webpage and click on some link it will open the link but when I want to go back to the first page by clicking the back button, it directly exits the program.
    Need help fast!!!

    Can you write a new article on going back to the primary fragment. Thanks.

    1. You can add this code to MainActivity:

      and replace onTabUnselected and onTabSelected methods:

      1. Sir, Is it a much to ask if I asked you to make a post on displaying three different web pages on three different tabs. I tired the thing you said it works but when I try to replace tab1 and tab2 with tab3 then it doesn’t work. the app exits after I press back button before going to the parent fragment.

        Let me put it clear.
        I want 5 tabs with different web pages. and in every web pages after i click a link I should be able to go back to the previous fragment.
        I would be so much thankful if you could help.

        1. What should the back button do?
          Is it like the back button in the browser, i.e. open the previous page in the web view?
          If so the code in my last comment does this, but it works only for the third tab because of the code in onTabSelected, but you can extend to the other tabs.
          But maybe you want the back button going to a specific fragment or tab.
          If so you can try:

          1. Yes, I want it like back button in the browser. but with this code now when ever I do back it goes to tab 1. I mean when I am in tab 1 and open a link than when i do back it should go to previous link after that may be exit the software.

      2. Hello, first of all thank you for the fantastic tutorials you have on the web.
        I would like to ask you a question, how can I make BACK button works alike in all WebView? If I explain the code as above only works with WebView1 the rest exits the application.

        Thank you very much.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.