Question Logique pour utiliser plusieurs vues Web dans TabLayout pour gérer les problèmes de mémoire


J'ai presque 30 webview dans un tablayout. Tout fonctionne bien, mais mon application consomme beaucoup de mémoire et se contentera de fermer à cause de problèmes de mémoire. C'est ce que je reçois dans le journal

04-05 21:00:09.458 19720-19801/com.example.choman.webview A/chromium: [FATAL:memory.cc(19)] Out of memory. size=16777216

Ceci est mon fichier java. Fondamentalement, tous les 29 fragments restants contiennent le même code avec juste une modification de l'URL. Je ne sais pas comment gérer cela.

public class stackOverflow extends Fragment {


    private WebView webView;
    private ProgressBar progressBar1;
    private SwipeRefreshLayout mSwipeRefreshLayout1;




    public stackOverflow() {
        // Required empty public constructor
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment


        return inflater.inflate(R.layout.fragment_tab1, container, false);


    }



    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {


        progressBar1 = (ProgressBar) view.findViewById(R.id.progressBar1);

        webView = (WebView) view.findViewById(R.id.website_detail_1);

        webView.setWebViewClient(new MyAppWebViewClient());
        webView.getSettings().setJavaScriptEnabled(true);
        webView.getSettings().setDomStorageEnabled(true);

        webView.loadUrl("http://www.stackoverflow.com");


        WebSettings webSettings = webView.getSettings();

        webView.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
        webView.getSettings().setAppCacheEnabled(true);
        webSettings.setDomStorageEnabled(true);

        webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);


        mSwipeRefreshLayout1 = (SwipeRefreshLayout) view.findViewById(R.id.swipe1);
        mSwipeRefreshLayout1.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                webView.loadUrl("http://www.stackoverflow.com");
            }
        });

        if (mSwipeRefreshLayout1.isRefreshing()) {
            mSwipeRefreshLayout1.setRefreshing(false);
        }


        webView.setOnKeyListener(new View.OnKeyListener() {
            @Override
            public boolean onKey(View v, int keyCode, KeyEvent event) {
                if ((keyCode == KeyEvent.KEYCODE_BACK) && webView.canGoBack()) {
                    webView.goBack();
                    return true;
                }

                return false;
            }
        });

    }

    public class MyAppWebViewClient extends WebViewClient {

        @Override
        public void onPageFinished(WebView view, String url) {
            super.onPageFinished(view, url);
            //view.findViewById(R.id.progressBar1).setVisibility(View.GONE);
            Log.i("pageFinished", "yesss");
            //progressBar.setVisibility(View.INVISIBLE);
            progressBar1.setVisibility(View.GONE);


            if (mSwipeRefreshLayout1.isRefreshing()) {
                mSwipeRefreshLayout1.setRefreshing(false);
            }


        }

        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            super.onPageStarted(view, url, favicon);
        }


        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            view.loadUrl(url);
            return true;
        }


    }
}

Activité principale

public class MainActivity extends AppCompatActivity
        implements NavigationView.OnNavigationItemSelectedListener {
    public WebView view;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);


        TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);


        tabLayout.addTab(tabLayout.newTab().setText("WebView1").setTag("WebView1"));
//all the way down to .....
tabLayout.addTab(tabLayout.newTab().setText("WebView30").setTag("WebView30"));        

        final ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
        viewPager.setOffscreenPageLimit(6);


        final PagerAdapter adapter = new TabPagerAdapter(getSupportFragmentManager(), tabLayout
                .getTabCount());
        viewPager.setAdapter(adapter);

        viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(
                tabLayout));
        tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {
                viewPager.setCurrentItem(tab.getPosition());
            }

            @Override
            public void onTabUnselected(TabLayout.Tab tab) {

            }

            @Override
            public void onTabReselected(TabLayout.Tab tab) {

            }
        });


        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
                this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        drawer.setDrawerListener(toggle);
        toggle.syncState();

        NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
        navigationView.setNavigationItemSelectedListener(this);

    }

    @Override
    public void onBackPressed() {
        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        if (drawer.isDrawerOpen(GravityCompat.START)) {
            drawer.closeDrawer(GravityCompat.START);
        } else {
            super.onBackPressed();
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        //    int id = item.getItemId();

//        //noinspection SimplifiableIfStatement
//        if (id == R.id.action_settings) {
//            return true;
//        }

        return super.onOptionsItemSelected(item);
    }

    @SuppressWarnings("StatementWithEmptyBody")
    @Override
    public boolean onNavigationItemSelected(MenuItem item) {

        ViewPager viewPager = (ViewPager) findViewById(R.id.pager);

        // Handle navigation view item clicks here.
        int id = item.getItemId();

        if (id == R.id.WebView1) {

            viewPager.setCurrentItem(0);

//all the way down to..30

 if (id == R.id.WebView30) {

            viewPager.setCurrentItem(30);






        }

        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        drawer.closeDrawer(GravityCompat.START);
        return true;
    }
}

Ceci est le code pour TabPagerAdapter

public class TabPagerAdapter extends FragmentStatePagerAdapter
{

    int tabCount;


    public TabPagerAdapter(FragmentManager fm, int numberOfTabs)
    {
        super(fm);
        this.tabCount = numberOfTabs;

    }


    @Override
    public Fragment getItem(int position)
    {
        switch (position)
        {
            case 0:
//
                WebViewFragment1 tab1 = new WebViewFragment1();
                return tab1;

   //all the way to tab 29

    webViewFragment30 tab30 = new WebViewFragment30();
return tab30



            default:
                return null;

        }

    }

    @Override
    public int getCount()
    {
        return tabCount;
    }
}

14
2018-04-05 15:28


origine


Réponses:


Utilisation ViewPager. ViewPager contiendra au maximum 3 fragments en mémoire à tout moment (sans modifier la limite de page par défaut de l’écran). Les 3 fragments sont les fragments visibles actuels, les fragments latéraux gauche et droit du fragment actuel.

Si vous voulez des onglets, vous pouvez créer une vue personnalisée qui ressemble aux onglets du système et l'ajouter au-dessus du ViewPager. Utilisation PageTransformer avec ViewPager pour suivre le ViewPager faites glisser et faites défiler l’onglet personnalisé en conséquence. Ensuite, écoutez les clics des onglets et faites défiler les ViewPager basé sur l'onglet pressé.

Mettre à jour:

J'ai totalement oublié que nous pourrions attacher un TabLayout avec un ViewPager au lieu de créer des onglets personnalisés.

tabLayout.setUpWithViewPager(viewpager) marchera.

Merci à @choman


8
2018-04-28 09:14



En citant votre commentaire, "je n’utilise que la seule vue Web dans l’application, mais ma page Web a une taille de 6,5 Mo. C’était la principale raison du crash de l’application".

Si votre page Web a une taille de 6,5 Mo, mon impression est que cela est dû à certaines images de grande qualité et de grande taille. Si tel est le cas, vous devriez envisager de réduire la taille des images en effectuant une réduction / un sous-échantillonnage des images. Réduire la taille des images côté serveur est bien mieux que de le faire dans le mobile après le téléchargement (gaspillage de bande passante, CPU, batterie).


4
2018-05-02 06:28



viewPager.setOffscreenPageLimit(6); Cette ligne est à l'origine du problème. Cette ligne indique au téléavertisseur de garder en mémoire (6 + 6 + 1 = 13) pages, ce qui devrait être coûteux dans votre cas puisque chaque page contient 6,5 Mo de contenu. Vous devez le changer pour viewPager.setOffscreenPageLimit(1) corriger le problème OutOfMemory.


4
2018-05-03 05:00



WebView est un composant lourd.

Je recommanderais de modifier votre application pour qu'elle fonctionne avec une seule vue Web et que vous modifiez l'URL à la place de l'utilisation de plusieurs vues Web.


2
2018-04-28 09:30



Vous pouvez utiliser android: largeHeap = "true" pour demander une plus grande taille de tas, mais cela ne fonctionnera pas sur les appareils pré-Honeycomb. Sur les appareils pré 2.3, vous pouvez utiliser la classe VMRuntime, mais cela ne fonctionnera pas sur Gingerbread et les versions ultérieures.

cela est dû au fait que votre application nécessite plus d'espace pour fonctionner. Je pense que cela vous aidera à résoudre le problème actuel. --comment utiliser--

<application
        ....
        android:largeHeap="true" >

Merci


2
2018-05-02 10:39