How to mark an action

I use this code to return to the activity stack (mainly to switch to home activity):

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


So, I create a new Intent and set the "target" to HomeActivity, which is on the action stack, so the whole stack will be cleared from above to this HomeActivity.
Now I need a slightly different use case. I have, for example, five ABCDE operations (A started by B, etc.) on the stack. Now I need to jump from E to C or B depending on what the user selects. The problem is that actions A, B, C, D, E have the same class. Therefore, I can’t use the example above because I don’t know how to target this activity.
So the question is whether there is a way to “lose activity” or manipulate the stack.
Thanks!

+7
source share
7 answers

The best and easiest solution (so far) would be to use fragments and the FragmentManager. Then tag each snippet and use the FragmentManager. Using only Activity can be very difficult to get almost the same result.

0
source

I have not tried this myself, but I think the best option would be to refactor your application to use the Fragment stack within the same Activity (since then you can more easily control the still frames using the provided addToBackStack() and popBackStack() ) . Basically this involves moving most of the code in your activity into a fragment, and then adding the Backstack manipulation code to the Activity). You can look at the FragmentBreadCrumbs code (with API 11+) or the code for HanselAndGretel (for use with the compatibility library) to see how this can be implemented.

However, if you want to continue to use your current multitasking approach, the following code that I have provided to illustrate how you can do this.

First, add a few inner classes for the alias of your current action and put these classes in a sequence list (note also the simplified getSequencedActivityIntent() method that I wrote, you can add more complex logic if you need to - maybe use a HashMap to bind each class in sequence with arbitrary tag value?):

 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 } 

Remember to also add your entries to your AndroidManifest.xml file ( singleTop is optional - this will cause the Activity instance on the stack to be created again when you return to the foreground):

  <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" /> 

Now that you need to launch a new “top” instance of your activity, you can do something like:

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

And when you need to return to one of the instances in the backstack, you can do:

  final Intent intent = getSequencedActivityIntent(- stepBack); if (intent == null) return; intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivity(intent); 
+2
source

You can index your actions without worrying about how to handle the entire onActivityResult chain with the super-activity that you distribute in all your actions.

Here is the implementation (I have not tested it), but if you extend this SuperActivity in all your actions, you can call fallBackToActivity( int ) for any activity using its index, and each kind of activity now has getIndex (). You can use it to return to a relative index, e.g. 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(); } } } } 
+2
source

You can simply save the condition in your statement if the user selects this item, pass the intention to class B and if the user chooses to transfer this element to class C

+1
source

Add extra to indicate what to do. for example

  intent.putExtra("STATE", 1); 

And get this value in onCreate of your activity.

  getIntent().getExtras() 
+1
source

As I understand it, Android only targets an activity class, not a specific example of activity. So, I think you cannot do what you want by simply adding some flags to the Intent.

I think that the easiest approach would be to implement it yourself, for example, in this way

a) Create some singleton and include in it an element that indicates the instance of activity that you want to return to (for example, operation B). You will probably have to store all the actions in a list in order to be able to get an instance of some previously launched actions.

b) Override onResume for all actions and perform the following check in it:

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

c) As soon as you need to return from E do

 SomeSingleton.setTargetActivity(B); finish(); 

This will close the top activity (which is E) and call the function in action D. It will check if it aims. If it is not, then it will close it, and the system will call onResume on C activity, etc.

+1
source

If you want to use an abnormal approach or a little more complicated, you will have more problems later. I think you can

Define an abstract / non-abstract subclass of Activity and define whatever you want. If the other classes are exactly the same as above, then just subclass from it and do nothing. But if the classes (actions) may differ from each other, you can provide abstract / non-abstract methods for defining additional capabilities.

So,

  • You write reusable codes for all types of activities,
  • You are acting normally to get a good result.
  • You can control everything that specializes in your activities.
  • You can control the stack using the manifest file
  • and more

For more details see below codes:

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

First activity:

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

Second activity:

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

main.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> 

manifest:

 <?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> 
+1
source

All Articles