9

我正在使用此代码跳回活动堆栈(主要是移动到家庭活动):

Intent goTo = new Intent(this, HomeActivity.class);
goTo.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(goTo);


因此,我创建了新的 Intent 并将“目标”设置为 Activity 堆栈中的 HomeActivity,因此整个堆栈将从顶部清除到此 HomeActivity。
现在我需要稍微不同的用例。例如,我在堆栈上有五个活动 ABCDE(A 开始 B 等)。现在我需要根据用户的选择从 E 跳到 C 或 B。问题是活动 A、B、C、D、E 具有相同的类别。所以我不能使用上面的例子,因为我不知道如何定位那个 Activity。
所以问题是是否有任何方法可以“标记活动”或使用堆栈进行操作。
谢谢!

4

7 回答 7

3

我自己没有尝试过,但我认为最好的选择是重构您的应用程序以Fragment在单个中使用 s堆栈Activity(因为您可以使用提供的addToBackStack()popBackStack()方法更轻松地管理后台堆栈)。基本上,这涉及将 Activity 中的大部分代码移动到 Fragment 中,然后在 Activity 中添加 backstack 操作代码)。您可以查看FragmentBreadCrumbs(使用 API 11+)的代码或HanselAndGretel的代码(用于与兼容性库一起使用),以了解如何实现。

但是,如果您想继续使用当前的多活动方法,以下是我想出的一些代码来说明如何做到这一点。

首先,添加几个内部类来为您当前的 Activity 设置别名,并将这些类放入序列列表中(还要注意getSequencedActivityIntent()我编写的简单方法,如果需要,您可以添加更高级的逻辑 - 可能使用 HashMap 来关联序列中的每个类带有任意标签值?):

public class MyActivity extends Activity {

    public static class A extends MyActivity {}
    public static class B extends MyActivity {}
    public static class C extends MyActivity {}
    public static class D extends MyActivity {}
    public static class E extends MyActivity {}
    public static class F extends MyActivity {}
    public static class G extends MyActivity {}
    public static class H extends MyActivity {}
    public static class I extends MyActivity {}
    public static class J extends MyActivity {}

    private final static List<Class<?>> SEQUENCE = Arrays.asList(new Class<?>[] {
            A.class, B.class, C.class, D.class, E.class,
            F.class, G.class, H.class, I.class, J.class,
    });

    private Intent getSequencedActivityIntent(int step) {
        final int current = SEQUENCE.indexOf(this.getClass());
        if (current == -1) new Intent(this, SEQUENCE.get(0));

        final int target = current + step;
        if (target < 0 || target > SEQUENCE.size() - 1) return null;

        return new Intent(this, SEQUENCE.get(target));
    }

    // the rest of your activity code
}

不要忘记将它们的条目也添加到您的 AndroidManifest.xml 文件中(singleTop是​​可选的 - 它会阻止堆栈中的 Activity 实例在返回到前面时再次创建):

    <activity android:name=".MyActivity$A" android:launchMode="singleTop" />
    <activity android:name=".MyActivity$B" android:launchMode="singleTop" />
    <activity android:name=".MyActivity$C" android:launchMode="singleTop" />
    <activity android:name=".MyActivity$D" android:launchMode="singleTop" />
    <activity android:name=".MyActivity$E" android:launchMode="singleTop" />
    <activity android:name=".MyActivity$F" android:launchMode="singleTop" />
    <activity android:name=".MyActivity$G" android:launchMode="singleTop" />
    <activity android:name=".MyActivity$H" android:launchMode="singleTop" />
    <activity android:name=".MyActivity$I" android:launchMode="singleTop" />
    <activity android:name=".MyActivity$J" android:launchMode="singleTop" />

现在,每当您需要启动 Activity 的新“顶级”实例时,您可以执行以下操作:

    final Intent intent = getSequencedActivityIntent(+1);
    if (intent == null) return;
    intent.putExtra("dataset", dataSet);
    startActivity(intent);

当您需要返回后台堆栈中的一个实例时,您可以执行以下操作:

    final Intent intent = getSequencedActivityIntent(- stepBack);
    if (intent == null) return;
    intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    startActivity(intent);
于 2012-08-28T17:26:13.023 回答
3

您可以索引您的活动,而不必担心onActivityResult使用您在所有活动中扩展的超级活动来处理所有链

这是一个实现(我没有测试它),但是如果你在所有的活动中扩展这个 SuperActivity,你可以fallBackToActivity( int )使用它的索引调用任何活动,每个活动现在都有一个 getIndex()。您可以使用它回退到相对索引,例如getIndex()-3

package sherif.android.stack.overflow;

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

public class SuperActivity extends Activity {
    private static String EXTRA_INDEX = "SUPER_INDEX";
    private static int RESULT_FALLBACK = 0x123456;
    private int index;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if(getIntent()!=null) {
            index = getIntent().getIntExtra(EXTRA_INDEX, -1) + 1;
        }
    }
    protected final int getIndex() {
        return index;
    }
    protected final void fallBackToActivity(int index) {
        Intent intent = new Intent();
        intent.putExtra(EXTRA_INDEX, index);
        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.getIntExtra(EXTRA_INDEX, -1)!=getIndex()) {
                setResult(RESULT_FALLBACK, data);
                finish();
            }
        }
    }
}
于 2012-08-31T12:39:10.683 回答
2

如果用户选择此项目将意图传递给 B 类,并且如果用户选择该项目将意图传递给 C 类,则您可以在语句中保留一个条件

于 2012-08-23T11:18:17.213 回答
2

为您的意图添加额外的内容,以指示活动要做什么。例如

    intent.putExtra("STATE", 1);

并在您的活动的 onCreate 中获取此值。

  getIntent().getExtras()
于 2012-08-23T11:20:29.297 回答
2

据我了解,Android 仅针对活动类,而不是特定的活动实例。所以,我认为你无法通过在 Intent 上添加一些标志来做你想做的事。

我认为最简单的方法是通过类似这样的方式自行实施

a)创建一些单例并在其中包含一个成员,该成员指向您要返回的活动实例(如示例活动 B)。可能,您必须将所有活动存储在某个列表中,以便能够获取某些先前启动的活动的实例。

b) 覆盖所有活动的 onResume 并在其中进行以下检查:

if (SomeSingleton.getTargetActivity() != null && this != SomeSingleton.getTargetActivity())
  finish();
else
   SomeSingleton.setTargetActivity(null);

c) 只要你需要从 E 回来就做

SomeSingleton.setTargetActivity(B);
finish();

这将关闭顶级活动(即 E)并在活动 D 上调用 onResume。它将检查它是否是目标。如果不是,那么它将关闭它,系统将在活动 C 上调用 onResume 等等。

于 2012-08-29T21:06:52.760 回答
2

如果你想使用异常的方法,或者一些棘手的地方,你以后会遇到更多的问题。我想你可以

定义 Activity 的抽象/非抽象子类并定义你想要的一切。如果其他类与上述类完全一样,那么就从它继承子类,什么都不做。但是如果类(活动)可能彼此不同,您可以提供抽象/非抽象方法来定义额外的能力。

所以

  • 您为所有活动编写可重用的代码,
  • 你表现正常,所以你会得到好的结果
  • 您可以控制活动中专门的所有内容
  • 您可以使用清单文件控制堆栈
  • 和更多

有关详细信息,请参见以下代码:

家长活动:

public abstract class AbstractActivity extends Activity {

    AbstractActivity currentActivity;


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        currentActivity = this;
        someProtectedMethod();
        commonMethod();
        // etc...

        /* event handling */
        Button btn_first = (Button) findViewById(R.id.btn_first);
        Button btn_second = (Button) findViewById(R.id.btn_second);

        btn_first.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                Intent intent = new Intent(currentActivity, FirstActivity.class);
                currentActivity.startActivity(intent);
            }
        });

        btn_second.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                Intent intent = new Intent(currentActivity, SecondActivity.class);
                currentActivity.startActivity(intent);
            }
        });

    }


    /** you must override it, so you can control specified things safe */
    protected abstract void someProtectedMethod();


    protected void commonMethod() {
        Log.i("LOG", "Hello From " + getClass().getName());
    }


    @Override
    protected void onResume() {
        super.onResume();
        //some statement that work in all activities to
        Log.i("LOG", "On Resume: " + getClass().getName());
    }
}

第一个活动:

public class FirstActivity extends AbstractActivity {

    @Override
    protected void someProtectedMethod() {
        Log.i("LOG", "Special Action From First Activity");
    }
}

第二个活动:

public class SecondActivity extends AbstractActivity {

    @Override
    protected void someProtectedMethod() {
        Log.i("LOG", "Special Action From Second Activity");
    }
}

主.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="horizontal" >


    <Button
        android:id="@+id/btn_first"
        android:layout_width="0dip"
        android:layout_height="wrap_content"
        android:layout_weight="0.5"
        android:text="Open First Activity" />

    <Button
        android:id="@+id/btn_second"
        android:layout_width="0dip"
        android:layout_height="wrap_content"
        android:layout_weight="0.5"
        android:text="Open Second Activity" />

</LinearLayout>

显现:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.activity_control"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="7" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".FirstActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

        <activity
            android:name=".SecondActivity"
            android:label="@string/app_name" >
        </activity>

    </application>

</manifest>
于 2012-09-01T04:17:50.283 回答
2

最好和最简单的解决方案(到目前为止)将使用 Fragments 和 FragmentManager。然后标记每个 Fragment 并使用 FragmentManager。仅使用 Activity 可能很难获得几乎相同的结果。

于 2012-09-03T13:05:56.010 回答