Android 组织碎片活动导航堆栈

Android 组织碎片活动导航堆栈,android,android-intent,android-activity,Android,Android Intent,Android Activity,应用程序(目标API级别必须为7)具有FragmentActivity,它在onCreate分析作为额外密钥传递的片段密钥 现在需要的是重新排序到前面已经用给定的片段键创建的活动 假设具有不同片段键的FragmentActivity是FA1、FA2和FA3——每个都是具有不同片段的相同活动类实例 现在,在堆栈FA1FA2FA3中,我想使用intent而不是back按钮进入FA2,默认情况下,这会给出: FA1FA2FA3>新增FA2 我想得到FA1FA3FA2,因为FA3可能有一些挂起的操作,F

应用程序(目标API级别必须为7)具有
FragmentActivity
,它在
onCreate
分析作为额外密钥传递的片段密钥

现在需要的是重新排序到前面已经用给定的片段键创建的活动

假设具有不同片段键的
FragmentActivity
FA1
FA2
FA3
——每个都是具有不同片段的相同活动类实例

现在,在堆栈
FA1
FA2
FA3
中,我想使用intent而不是back按钮进入
FA2
,默认情况下,这会给出:

FA1
FA2
FA3
>新增
FA2

我想得到
FA1
FA3
FA2
,因为
FA3
可能有一些挂起的操作,
FA1
FA2
没有默认值好,但肯定比默认值好

如果有多个活动,我会使用
标志\u ACTIVITY\u REORDER\u TO\u FRONT
标志来表示意图,但在这种情况下不起作用


FA1、FA2、FA3等。
都是同一类的实例
MyFA
,这就是为什么我不能使用intent标志,而FragmentManager似乎在出现标准的全局碎片缓存之前帮不上忙


里程碑(目前正在工作,有待改进)解决方案我今天学到的一件事是,允许为同一活动制作多个别名,并将不同的意图附加项用作id。现在有了REORDER_TO_FRONT标志,它可以按照我的要求工作

解决方案反馈解决方案没有低级操作,我更喜欢在任务或后台挖掘。现在的缺点是,每个这样的活动都需要一个带有硬编码路径的单独别名,我不太喜欢它

需求(赏金在这里)任何一个拥有合理优化的人都会得到150300块饼干。不错吧?任何其他固溶体也受到高度赞赏

目前我在应用程序清单上有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>

您可以研究如何使用提供的功能。它具有
popbackbackstack
等功能

您还可以使用将片段添加到Backback。您可以使用
addToBackStack
来完成此操作


因此,有了这两个类,您应该能够根据需要在backbackback中重新排序您的片段。

这个答案相当于300个cookies:-D mmmm

  • 扩展应用程序,以便我们可以创建具有全局范围的自己的后台堆栈列表。

    导入android.app.Application; 导入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));
        }
    }
    
    }

  • 覆盖后退按钮,这样我们就可以使用自己的后退堆栈而不是Android的。

  • 编辑

    我提出了一个概念证明

    • 专业人士
      • 没有别名
      • 完全动态且可重用
      • 低电平控制
      • 易于使用(扩展CustomBackbackActivity而不是FragmentActivity或Activity)
    • 缺点
      • 不是现成的解决方案。将需要调整和调试
    在我的谷歌硬盘上

    完整的

    拉链

    请不要抱怨我的代码。我知道我在应该使用常量的地方使用了字符串,我复制了代码,而不是将代码分开,我的间距不是完美的,我使用了过多的循环和对象。我还没有整理好储蓄状态。同样,这只是一个概念证明。它是有效的,我认为它可能会帮助某些人。

    以下是解决方案:

    1。
    FragmentActivity
    中,为从片段到活动的回调实现一个
    接口

    2.当您启动任何片段时,请将其与参数或标记一起放入后堆栈中
    (addToBackStack(String arg0))
    ,在该参数的帮助下,您可以弹出该标记


    3.当需要对片段进行重新排序时,请调用接口的方法,该方法根据需要使用适当的参数实现,然后使用
    popBackStack(字符串arg1,字符串arg2)
    获取带有标记的片段,标记放在backstack中。

    我已经回答了类似的问题,但解决方案不是最好的,因为FA1>FA2>FA3会将您带到FA1>FA2,而不是FA1>FA3>FA2

    无论如何,我对代码进行了一些编辑,以使用一个“标记”,它将是一个字符串,但我认为您可以使用使用整数索引的主要解决方案。总之,这应该允许您使用某个标记返回活动。我不确定每个活动如何决定它的标签,但在我之前的回答中,这是一个简单的递增整数问题

    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();
                }
            }
        }
    }
    

    基于您使用
    activity alias
    解决此问题的想法,我编写了一个解决方案,将执行以下操作:

    • 扫描程序包中的活动列表以查找特定活动的别名
    • 设置将每个别名映射到目标的查找表
    • 提供一个
      startActivity()
      activitydestromed()
      方法,这些方法将进行一些簿记,以便可以使用查找表根据意图动态地为正在运行的活动分配别名
    下面是一个关于如何使用它的示例:

    • 在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" />
      
      您可以这样做:

          Intent intent = new Intent(this, MyFragmentActivity.class);
          intent.putExtra("title", newActivityTitle);
          intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
          mHistorian.startActivity(this, intent);
      
      因此,您仍然需要将一些
      活动别名
      手动添加到清单中(用作池),并在活动中实现
      matchIntent()
      方法(以帮助检测两个意图是否等于您),但其余的由Historian类动态处理

      我还没有对代码进行详尽的测试,但在某些sim卡上似乎工作得很好
      <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" />
      
      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);