web-dev-qa-db-ja.com

Androidタブの変更時にフラグメントの更新を停止する方法

私は次のコードを持っています:

MainActivity.Java

package com.erc.library;

import Java.io.BufferedInputStream;
import Java.io.File;
import Java.io.FileOutputStream;
import Java.io.InputStream;
import Java.net.URL;
import Java.net.URLConnection;

import Android.app.ActionBar;
import Android.app.ActionBar.Tab;
import Android.app.FragmentTransaction;
import Android.content.SharedPreferences;
import Android.content.res.Resources;
import Android.graphics.Color;
import Android.os.Bundle;
import Android.os.Environment;
import Android.os.StrictMode;
import Android.support.v4.app.FragmentActivity;
import Android.support.v4.view.ViewPager;
import Android.view.Menu;
import Android.view.MenuInflater;
import Android.view.MenuItem;
import Android.widget.TextView;
import Android.widget.Toast;

import com.erc.sayeghlibrary.adapter.TabsPagerAdapter;

public class MainActivity extends FragmentActivity implements
        ActionBar.TabListener {

    private ViewPager viewPager;
    private TabsPagerAdapter mAdapter;
    private ActionBar actionBar;
    // Tab titles
    private String[] tabs = { "Stories", "Dictionaries", "eBooks"};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);






        int actionBarTitleId = Resources.getSystem().getIdentifier("action_bar_title", "id", "Android");
        if (actionBarTitleId > 0) {
            TextView title = (TextView) findViewById(actionBarTitleId);
            if (title != null) {
                title.setTextColor(Color.WHITE);
            }
        }       

        // Initilization
        viewPager = (ViewPager) findViewById(R.id.pager);
        actionBar = getActionBar();
        mAdapter = new TabsPagerAdapter(getSupportFragmentManager());

        viewPager.setAdapter(mAdapter);
        actionBar.setHomeButtonEnabled(false);
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);


        // Adding Tabs
        for (String tab_name : tabs) {
            actionBar.addTab(actionBar.newTab().setText(tab_name)
                    .setTabListener(this));
        }

        /**
         * on swiping the viewpager make respective tab selected
         * */
        viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {

            @Override
            public void onPageSelected(int position) {
                // on changing the page
                // make respected tab selected
                actionBar.setSelectedNavigationItem(position);
            }

            @Override
            public void onPageScrolled(int arg0, float arg1, int arg2) {
            }

            @Override
            public void onPageScrollStateChanged(int arg0) {
            }
        });







    }

    @Override
    public void onTabReselected(Tab tab, FragmentTransaction ft) {
    }

    @Override
    public void onTabSelected(Tab tab, FragmentTransaction ft) {
        // on tab selected
        // show respected fragment view
        viewPager.setCurrentItem(tab.getPosition());


    }

    @Override
    public void onTabUnselected(Tab tab, FragmentTransaction ft) {
    }






       @Override
       public boolean onCreateOptionsMenu(Menu menu) {
         MenuInflater inflater = getMenuInflater();
         inflater.inflate(R.menu.main, menu);
         return true;
       } 




       @Override
       public boolean onOptionsItemSelected(MenuItem item) {
         switch (item.getItemId()) {
         // action with ID action_refresh was selected
         case R.id.Favorites:
           Toast.makeText(this, "Favorites selected", Toast.LENGTH_SHORT)
               .show();
           break;
         // action with ID action_settings was selected

         default:
           break;
         }

         return true;
       } 


}

TabsPagerAdapter.Java

package com.erc.library.adapter;

import com.erc.library.Dictionaries;
import com.erc.library.Ebooks;
import com.erc.library.Stories;

import Android.support.v4.app.Fragment;
import Android.support.v4.app.FragmentManager;
import Android.support.v4.app.FragmentPagerAdapter;

public class TabsPagerAdapter extends FragmentPagerAdapter {

    public TabsPagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int index) {

        switch (index) {
        case 0:

            return new Stories();
        case 1:

            return new Dictionaries();
        case 2:
            // Movies fragment activity
            return new Ebooks();
        }

        return null;
    }

    @Override
    public int getCount() {
        // get item count - equal to number of tabs
        return 3;
    }

}

私は、ナビゲーションがタブによるライブラリアプリケーションを作成しています。問題は、3番目のタブから1番目または1番目から3番目のタブに移動するたびに、タブのコンテンツが更新され、更新を防ぎたい、助けてください ?

36
Monzer Yaghi

デフォルトでは、ViewPagerは、ページをスワイプするとフラグメントを再作成します。これを防ぐには、次の3つのいずれかを試してください。

1。フラグメントのonCreate()で、setRetainInstance(true)を呼び出します。

2。フラグメントの数が固定されていて比較的小さい場合、onCreate()に次のコードを追加します。

mViewPager = (ViewPager)findViewById(R.id.pager);
mViewPager.setOffscreenPageLimit(limit);         /* limit is a fixed integer*/

3。FragmentPagerAdapterの一部として ViewPager を使用します。

私の記憶が正しければ、2番目のオプションはより有望です。ただし、3つすべてを試して、どれが機能するかを確認することをお勧めします。

107
Y.S

最初にFragmentPagerAdapterをインスタンス化する必要があり、次に.getCount()は値を返します-

一方、.getCount() - 1はデフォルトのオフスクリーン制限として設定する必要があります。

TabsPagerAdapter adapter = new TabsPagerAdapter(getSupportFragmentManager());

/* the ViewPager requires a minimum of 1 as OffscreenPageLimit */
int limit = (adapter.getCount() > 1 ? adapter.getCount() - 1 : 1);

ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
viewPager.setAdapter(adapter);
viewPager.setOffscreenPageLimit(limit);
21
Martin Zeitler

ビューがnullかどうかを確認することで、ビューの再作成を処理できます。

public class FragmentExample extends Fragment {

    private View rootView;

    public FragmentExample() {}

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

    if (rootView == null) {

        rootView = inflater.inflate(R.layout.fragment_example_layout, container, false);

        // Initialise your layout here

    } else {
        ((ViewGroup) rootView.getParent()).removeView(rootView);
    }

    return rootView;
    }
}
4
Ahmad Nasser

フラグメントのonCreate()で、setRetainInstance(true)を呼び出します

3
Mohsen mokhtari

この質問に少し遅れましたが、Y.S。のおかげで、ViewPagerの仕組みを知ることができました。私は4つのタブを持つアプリを作成していましたが、いつでも2つのタブしか更新されていないことに気付きました。これはデフォルトの動作であると思われます。数時間の調査の後、Androidが複数のタブを更新して、ユーザーにスムーズなスワイプパフォーマンスをもたらすことを理解しました-tab2をクリックしたことに気付くかもしれませんが、Android tab3のデータを取り込み、準備を整えます。

この動作は優れていますが、長所と短所があります。長所-そのタブに到達したときに外部サーバーからデータがロードされることなく、スムーズなスワイプエクスペリエンスが得られます。短所-タブでのバックスタックの実装は投げに行く可能性があります。タブをクリックすると、ビューページャーは実際にはよりスムーズなタブを呼び出すため、クリックしたタブのバックスタックの内容に基づいてメソッドが左上にバックアロー(ホーム)を設定している場合、大きな問題が発生します。

setOffscreenPageLimitはこれに対する答えです。カスタムバックスタックフレームワークを機能させ、tab2がクリックされたときにtab3が呼び出されないようにするには、値をタブの数に設定するだけです。たとえば、4つのタブがある場合は、setOffScreePageLimit(4)を設定します。これは、Androidが最初に4つのフラグメントすべてをリフレッシュすることを意味します。これはパフォーマンスのオーバーヘッドです(適切に管理する必要があります)。ただし、バックスタックとタブの切り替えはそのままです。役立ちます。

アクティビティはActionBar.TabListenerを実装するため、アクティビティのonCreate()は何度も呼び出されます。そのため、onResume()メソッドに次のコードを配置します。

   // Initilization
    viewPager = (ViewPager) findViewById(R.id.pager);
    actionBar = getActionBar();
    mAdapter = new TabsPagerAdapter(getSupportFragmentManager());

    viewPager.setAdapter(mAdapter);
    actionBar.setHomeButtonEnabled(false);
    actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);


    // Adding Tabs
    for (String tab_name : tabs) {
        actionBar.addTab(actionBar.newTab().setText(tab_name)
                .setTabListener(this));
    }

    /**
     * on swiping the viewpager make respective tab selected
     * */
    viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {

        @Override
        public void onPageSelected(int position) {
            // on changing the page
            // make respected tab selected
            actionBar.setSelectedNavigationItem(position);
        }

        @Override
        public void onPageScrolled(int arg0, float arg1, int arg2) {
        }

        @Override
        public void onPageScrollStateChanged(int arg0) {
        }
    });
1

上記の私の場合、提案は機能しません。

フラグメントの再作成を制限するために、私がしたこと:

onCreateViewでは、次のコードのように、膨張したビューをグローバル変数に格納し、nullである場合にのみ初期化できます。

    var root:View?=null
    var apiDataReceived=false
 override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?,
                          savedInstanceState: Bundle?): View? {
    // Inflate the layout for this fragment
    if (root==null)
        root=inflater!!.inflate(R.layout.fragment_layout, container, false)
    return root
}

いくつかのデータを解析して、RecyclerViewまたは他のViewに入力する場合

  1. 上記のコードapiDataReceivedのようなグローバル変数を作成します

  2. データを正常に解析した場合は、trueに設定します。

  3. ApiCallsが次のような条件を設定する前に:

    if(!apiDataReceived){apiCalls()}

したがって、データが解析されない場合にのみapiCalls()が呼び出される場合。

Http呼び出しと解析、またはonCreateViewのようなonStartの後に呼び出されたメソッド内のその他のことを行います。

上記のコードはkotlinにあります。問題に直面している場合は、コメントでお知らせください。

0
Suraj Vaishnav