0

最新の Android アプリケーション (API レベル 15) では、GUI の各タブが PagerAdapter に登録された Fragment クラスによって表され、Tab イベントが TabListener によって処理される新しいアーキテクチャを使用しました。

ただし、2 つのタブ間でデータを送信したい場合、問題が発生します。このページのコード サンプルを使用し、次のコードを記述して、タブからアクティビティにデータを送信しました。

@Override
public void onDataReceived(Map<String, List<Map<Integer, String>>> receivedData) {

    Log.i("CarerActivity:onDataReceived", "Map received by Fragment.");
    Log.i("CarerActivity:onDataReceived", receivedData.toString());
    Log.i("Fragment ID", ""+R.id.configurationfragment);

    TabConfiguration configurationFragment = (TabConfiguration) getSupportFragmentManager().findFragmentById(R.id.configurationfragment);

    if(configurationFragment != null){
        Log.i("CarerActivity:onDataReceived", "Fragment not null.");
    }else{
        Log.i("CarerActivity:onDataReceived", "Fragment null!");
    }
}

receivedData.toString() が正しく表示されるため、タブはそのデータをアクティビティに送信します。フラグメント ID も表示されます。その後、出力は常に「CarerActivity:onDataReceived Fragment null!」になります。これにより、フラグメントのメソッドを呼び出すことができなくなります(nullであるため)。

私のR.Javaで行

public static final int configurationfragment=0x7f080001;

の下にあります

    public static final class id{

.

誰が私が間違っているのか、またはどこでエラーを探すべきか考えましたか?

セットアップ: Android 4.0.3、API レベル 15、Java 1.6、Mac OS 10.8、Eclipse Juno を搭載した Samsung Galaxy Nexus。

4

1 に答える 1

1

FragmentPagerAdapterに関する興味深い記事を次に示します。

FragmentPagerAdapter は、リストをスワイプすると各フラグメントをデタッチしますが、ユーザーがスワイプして戻るときに簡単に再アタッチできるように、フラグメントをメモリに保持します。Fragment の数が多い場合、FragmentStatePagerAdapter はそれらを削除するので検討する価値がありますが、ユーザーがスワイプしてそれらに戻るときに再構築する必要があるという欠点があります。したがって、フラグメントが少なく、より複雑な場合は FragmentPagerAdapter が適していますが、より大きなセットの場合は FragmentStatePagerAdapter を検討してください。

基本的に、あるフラグメントから別のフラグメントにスワイプすると、前のフラグメントは破棄されます (= null)。

この問題を解決する 1 つの方法は、新しいデータをサード パーティのクラスまたはアクティビティに保持することです。次に、フラグメントが再作成されたら、新しいデータを含むバンドルを渡します。

例を次に示します。

public class PagerUserAdapter extends FragmentStatePagerAdapter
{
    private final static String titles[] = {"Profile", "Badges", "Skills", "Accomplishments"};

    private Bundle args;

    public PagerUserAdapter(FragmentManager fm, CWUser u) 
    {
        super(fm);

        this.args = new Bundle();
        args.putSerializable(Constants.BUNDLE_USER, u);
    }

    public void refresh(CWUser u)
    {
        args.putSerializable(Constants.BUNDLE_USER, u);
        this.notifyDataSetChanged();
    }

    @Override
    public CharSequence getPageTitle(int position)
    {
        return titles[position];
    }

    @Override
    public Fragment getItem(int position) 
    {
        switch(position)
        {
        case 0:
            return ProfileFragment.newInstance(args);
        case 1:
            return BadgesFragment.newInstance(args);
        case 2:
            return SkillsFragment.newInstance(args);
        case 3:
            return AccomplishmentsFragment.newInstance(args);
        default:
            return ProfileFragment.newInstance(args);
        }
    }

    @Override
    public int getCount() 
    {
        return titles.length;
    }

    @Override
    public int getItemPosition(Object object) 
    {
        return POSITION_NONE;
    }
}

public class BadgesFragment extends BaseFragment
{    
    public static BadgesFragment newInstance(Bundle args)
    {
        BadgesFragment f = new BadgesFragment();
        f.setArguments(args);
        return f;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) 
    {
        super.onActivityCreated(savedInstanceState);

        CWUser u = (CWUser) getArguments().get(Constants.BUNDLE_USER);
            //do what you want with your new data   
    }
}

新しいデータを取得するときのアクティビティでは、新しいデータでアダプターの refresh メソッドを呼び出すだけです。これが私のやり方です。もっとエレガントな解決策があるかもしれません。どんな提案も受け付けています。この例は、私のオープン ソース アプリの 1 つに基づいています。掘り下げたい場合は、完全なコードを含むプロジェクトを次に示します。

于 2012-09-07T15:42:07.083 に答える