3

アプリケーション(ターゲット API レベルは 7 である必要があります)には、エクストラとして渡されたフラグメント キーFragmentActivityでの分析があります。onCreate

ここで必要なのは、指定されたフラグメント キーで既に作成されているアクティビティを先頭に並べ替えることです。

FragmentActivity異なるフラグメント キーを持つ が FA1FA2および- であるとしましょうFA3。それぞれが、異なるフラグメントを持つ同じアクティビティ クラス インスタンスです。

スタック内FA1> FA2>FA3戻るボタンではなくインテントを使用して にアクセスしたいのですがFA2、デフォルトでは次のようになります。

FA1> FA2> FA3> 新しいFA2

> >保留中の操作が ある可能性があるため、 FA1> FA3>はそれほど良くはありませんが、デフォルトよりも確実に優れています。FA2FA3FA1FA2

いくつかのアクティビティがあった場合FLAG_ACTIVITY_REORDER_TO_FRONT、インテントにフラグを使用しますが、この場合は機能しません。


FA1, FA2, FA3, etc.はすべて同じクラスのインスタンスですMyFA。そのため、インテント フラグを使用できず、標準のグローバル フラグメント キャッシュができるまで FragmentManager は役に立たないようです。


マイルストーン (現在動作中、改善予定) ソリューション今日私が学んだことの 1 つは、id として使用されるさまざまなインテント エクストラを使用して、同じアクティビティに複数のエイリアスを作成できるアクティビティ エイリアスですREORDER_TO_FRONT フラグを使用すると、希望どおりに機能します。

ソリューションのフィードバックソリューションには低レベルの操作はありません。タスクやバックスタックを掘り下げるよりもずっと好きです。欠点は、そのようなアクティビティのそれぞれに、ハードコードされたパスを持つ別のエイリアスが必要なことです。私はそれがあまり好きではありません。

要件 (報奨金はこちら)まともな最適化を行った人は誰でも150 300 個の Cookie を受け取ります。悪くない ?他の固溶体も高く評価されます。

現在、アプリケーション マニフェストに 10 個ほどのエイリアスがあります。

    <activity
        android:name=".activity.FragmentActivity"
        android:configChanges="orientation"
        android:screenOrientation="portrait" >
        <intent-filter>
            <category android:name="android.intent.category.DEFAULT" />

            <action android:name="com.company.name.intent.FragmentActivity" />
        </intent-filter>
    </activity>

    <activity-alias
        android:name="com.company.name.intent.FragmentActivity.FragmentedOne"
        android:targetActivity=".activity.FragmentActivity" >
        <intent-filter>
            <action android:name="com.company.name.intent.FragmentActivity.FragmentedOne" />

            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>

        <meta-data
            android:name="fragment_key_extra"
            android:value="FragmentOne" />
    </activity-alias>
    <activity-alias
        android:name="com.company.name.intent.FragmentActivity.FragmentedTwo"
        android:targetActivity=".activity.FragmentActivity" >
        <intent-filter>
            <action android:name="com.company.name.intent.FragmentActivity.FragmentedTwo" />

            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>

        <meta-data
            android:name="fragment_key_extra"
            android:value="FragmentTwo" />
    </activity-alias>

そして、アクティビティは次のように並べ替えられます

Intent intent = new Intent(
"com.company.name.intent.FragmentActivity.FragmentedOne");
intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(intent);
4

5 に答える 5

4

この答えは300クッキーの価値があります:-DMmmmm

  1. アプリケーションを拡張して、グローバルスコープで独自のバックスタックリストを作成できるようにします。

    import android.app.Application; import android.content.Intent;

    クラスMyAppはアプリケーションを拡張します{

    //This is our very own back stack.
    private ArrayList<Intent> backStack = new ArrayList<Intent>();
    
    public void reorderBackStack(){
        //Do what you want to the order of your backstack
        //You can read the value of your intent extras from here.
    }
    
    public void addIntent(Intent i){ // this gets called from our activities onCreate
        backStack.add(i);
    }
    
    public void goBack(){
        if(backStack.size() >= 2){ // can go back
            backStack.remove(backStack.size() - 1); // drop the last item in stack if you want.  This is how Android does it.  (no forward capability)
            this.startActivity(backStack.get(backStack.size() - 1));
        }
    }
    

    }

  2. アクティビティにカスタムバックスタックへの参照を追加します。

    public class MainActivity extends Activity {MyApp myapp;

     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_main);
         myapp = ((MyApp)getApplicationContext());
         myapp.addIntent(this.getIntent()); //add the intent for this instance to backStack.
         myapp.reorderBackStack(); // call this anytime we need to reorder the back stack.
     }
    
     @Override
     public void onNewIntent(Intent newIntent){
         this.setIntent(newIntent);
         myapp.addIntent(this.getIntent());
     }
    
     @Override
     public boolean onCreateOptionsMenu(Menu menu) {
         getMenuInflater().inflate(R.menu.activity_main, menu);
         return true;
     }
    
     @Override
     // We won't be using the back stack we will be using our own list of intents as a back stack so we need to override the back button.
     public boolean onKeyDown(int keyCode, KeyEvent event) {
         if (keyCode == KeyEvent.KEYCODE_BACK) {
             myapp.goBack();
             return true;
         }
         return super.onKeyDown(keyCode, event);
    }
    

    }

  3. Androidの代わりに独自のバックスタックを使用できるように、戻るボタンをオーバーライドします。

編集

概念実証をまとめました。

  • 長所
    • エイリアスなし
    • 完全に動的で再利用可能
    • 低レベル制御
    • 使いやすい(FragmentActivityまたはActivityの代わりにCustomBackStackActivityを拡張する)
  • 短所
    • すぐに使えるソリューションではありません。微調整とデバッグが必要になります。

.apkは私のグーグルドライブにあります。

完全なプロジェクトフォルダはここにあります

zip形式でダウンロード可能なプロジェクトフォルダはこちらです。

私のコードについて文句を言わないでください。定数を使用する必要がある場所で文字列を使用し、コードを分離する代わりに複製しました。間隔が完全ではなく、過剰なループとオブジェクトを使用しました。savedInstanceStateを整理していません。繰り返しますが、これは概念実証にすぎません。それはうまくいき、誰かを助けるかもしれないと思いました。

于 2012-10-24T02:40:20.770 に答える
2

解決策は次のとおりです。

1.FragmentActivity実装で、Interfaceフラグメントからアクティビティへのコールバックを実行します。

2.フラグメントを開始するときは、引数またはタグ(addToBackStack(String arg0))を使用してバックスタックに配置し、そのタグを使用してフラグメントをポップアップ表示できます。

3.フラグメントを並べ替える必要がある場合は、要件に従って適切な引数を使用して実装したインターフェイスのメソッドを呼び出し、popBackStack(String arg1, String arg2)バックスタックに配置したタグを使用してフラグメントを取得します。

于 2012-10-26T13:26:42.980 に答える
2

FragmentManagerが提供する機能を使用して調べることができます。などの機能がありますpopBackStack

FragmentTransactionを使用してフラグメントをバックスタックに追加することもできます。これを実現するために使用できますaddToBackStack

したがって、これら 2 つのクラスを使用すると、必要に応じてバックスタックでフラグメントを並べ替えることができるはずです。

于 2012-08-03T14:08:59.333 に答える
1

activity-aliasこの問題を解決するために使用するというあなたのアイデアに基づいて、次のことを行うヒストリアン クラスを作成しました。

  • パッケージ内のアクティビティ リストをスキャンして、特定のアクティビティのエイリアスを探します。
  • 各エイリアスをインテントにマップするルックアップ テーブルを設定します。
  • インテントに基づいて実行中のアクティビティにエイリアスを動的に割り当てるためにルックアップ テーブルを使用できるように、いくつかの簿記を行うstartActivity()およびメソッドを提供します。activityDestroyed()

使用方法の例を次に示します。

  • AndroidManifest.xml で

    <activity android:name=".MyFragmentActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <activity-alias android:name=".Alias0" android:targetActivity=".MyFragmentActivity" />
    <activity-alias android:name=".Alias1" android:targetActivity=".MyFragmentActivity" />
    <activity-alias android:name=".Alias2" android:targetActivity=".MyFragmentActivity" />
    <activity-alias android:name=".Alias3" android:targetActivity=".MyFragmentActivity" />
    <activity-alias android:name=".Alias4" android:targetActivity=".MyFragmentActivity" />
    
  • Activity クラス内

    public class MyFragmentActivity extends FragmentActivity
            implements Historian.Host {
    
        private Historian<MyFragmentActivity> mHistorian;
    
        // ...
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            mHistorian = new Historian<MyFragmentActivity>(this);
    
            // ...
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            mHistorian.activityDestroyed(this);
        }
    
        @Override
        public boolean matchIntent(Intent intent0, Intent intent1) {
            if (intent0 == null || intent1 == null) return false;
            final String title0 = intent0.getStringExtra("title");
            final String title1 = intent1.getStringExtra("title");
            return title0.equals(title1);
        }
    
        // ...
    
    }
    

次のようにアクティビティの新しいインスタンスを開始する代わりに:

    Intent intent = new Intent(this, MyFragmentActivity.class);
    intent.putExtra("title", newActivityTitle);
    intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
    startActivity(intent);

これをして:

    Intent intent = new Intent(this, MyFragmentActivity.class);
    intent.putExtra("title", newActivityTitle);
    intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
    mHistorian.startActivity(this, intent);

そのため、いくつかをマニフェストに手動で追加しactivity-alias(プールとして使用するため) matchIntent()、Activity にメソッドを実装する必要がありますが (2 つのインテントが等しいかどうかを検出するために)、残りは Historian クラスによって動的に処理されます。

コードを徹底的にテストしたわけではありませんが、私が行ったいくつかの簡単なテストでは問題なく動作するようです。アイデアは、実際には他の質問に対する私の答えと非常によく似ています(そこの代わりに使用する必要があります)が、内部の子クラスの代わりにを使用すると、はるかにきれいになります:)FLAG_ACTIVITY_CLEAR_TOPFLAG_ACTIVITY_REORDER_TO_FRONTactivity-alias

于 2012-11-01T05:42:22.977 に答える
1

私は同様のことを答えましたが、FA1 > FA2 > FA3 は FA1 > FA3 > FA2 ではなく FA1 > FA2 に移動するため、解決策は最善ではありません。

私の答えは質問に対するものでした:アクティビティにタグを付ける方法

とにかく、文字列になる「タグ」を使用するようにコードを少し編集しましたが、整数インデックスを使用する主なソリューションを使用できると思います。fallBackToActivity要約すると、これにより、特定の TAG を使用できるようになります。各アクティビティがタグをどのように決定するかはわかりませんが、以前の回答では、増分整数の単純な問題でした。

package sherif.android.stack.overflow;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;

public class SuperActivity extends FragmentActivity {
    private static String EXTRA_INDEX = "SUPER_INDEX";
    private static int RESULT_FALLBACK = 0x123456;
    private String tag; //this is your tag
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if(getIntent()!=null) {
            tag = getIntent().getStringExtra(EXTRA_INDEX, "default_tag");
        }
    }
    protected final String getIndex() {
        return tag;
    }
    protected final void fallBackToActivity(String tag) {
        Intent intent = new Intent();
        intent.putExtra(EXTRA_INDEX, tag);
        setResult(RESULT_FALLBACK, intent);
        finish();
    }
    //@Override
    //public void startActivityForResult(Intent intent, int requestCode) {
    //  intent.putExtra(EXTRA_INDEX, getIndex());
    //  super.startActivityForResult(intent, requestCode);
    //}
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if(resultCode == RESULT_FALLBACK) {
            if(!data.getStringExtra(EXTRA_INDEX, "default_tag").equals(getIndex())) {
                setResult(RESULT_FALLBACK, data);
                finish();
            }
        }
    }
}
于 2012-10-29T10:24:28.323 に答える