Câu hỏi Cách gắn thẻ Hoạt động


Tôi đang sử dụng mã này để nhảy trở lại trong hoạt động ngăn xếp (chủ yếu là để di chuyển đến nhà hoạt động):

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


Vì vậy, tôi tạo ra ý định mới và thiết lập "mục tiêu" để HomeActivity đó là trong hoạt động ngăn xếp để ngăn xếp toàn bộ sẽ được xóa từ đầu đến HomeActivity này.
Bây giờ tôi cần trường hợp sử dụng hơi khác nhau. Tôi có ví dụ năm Hoạt động A-B-C-D-E (A bắt đầu B, vv) trên ngăn xếp. Bây giờ tôi cần phải nhảy từ E đến C hoặc B tùy thuộc vào những gì người dùng chọn. Vấn đề là các hoạt động A, B, C, D, E có cùng một lớp. Vì vậy, tôi không thể sử dụng ví dụ ở trên vì tôi không biết cách nhắm mục tiêu Hoạt động đó.
Vì vậy, câu hỏi là nếu có bất kỳ cách nào để "hoạt động thẻ" hoặc thao tác với ngăn xếp.
Cảm ơn!


7
2017-08-23 11:10


gốc


nếu A và E là Same, thay vì gọi E tại sao bạn không gọi hoạt động A từ lịch sử ?? - Ishtiaq
Tôi đã chỉnh sửa câu hỏi của mình để làm rõ hơn. Tất cả các hoạt động đều có cùng lớp. - Warlock
Tôi không thể hiểu được vấn đề của bạn. Vui lòng cho tôi biết, điều gì là xấu? - Ilya Demidov
Nếu tôi hiểu đúng bạn, mỗi Hoạt động là cùng một lớp. Và trong tệp kê khai của bạn có 5 Hoạt động có cùng tên. Nếu đó là sự thật, nó sai. Bạn không thể xây dựng dự án này. Bạn sẽ gặp sự cố "hoạt động cộng hòa" - Ilya Demidov
Tôi có năm trường hợp (A, B, C, D, E) của cùng một Hoạt động (cùng một lớp) trên ngăn xếp. Tôi tạo ra chúng bằng cách sử dụng startActivity (context, MyClass.class) .Tôi muốn chuyển từ E sang C. Làm thế nào để làm điều đó? Trong ví dụ của tôi, tôi đang sử dụng FLAG_ACTIVITY_CLEAR_TOP nhưng tôi không biết cách nhắm mục tiêu Hoạt động phù hợp. Làm cách nào để phân biệt từng Hoạt động có cùng một lớp trong hàm dựng Intent? - Warlock


Các câu trả lời:


Tôi đã không thử nó bản thân mình, nhưng tôi nghĩ rằng các tùy chọn tốt nhất sẽ được refactor ứng dụng của bạn để sử dụng một chồng Fragmenttrong một đơn Activity (vì bạn có thể dễ dàng quản lý backstack hơn bằng cách sử dụng addToBackStack() và popBackStack() phương pháp). Về cơ bản, điều này liên quan đến việc di chuyển hầu hết mã trong Activity của bạn vào một Fragment và sau đó thêm mã thao tác backstack vào Activity). Bạn có thể xem mã cho FragmentBreadCrumbs (với API 11+) hoặc mã cho HanselAndGretel (để sử dụng với thư viện tương thích) để xem cách thực hiện điều này.

Tuy nhiên, nếu bạn muốn tiếp tục sử dụng phương pháp tiếp cận đa hoạt động hiện tại của mình, sau đây là một số mã tôi đã đưa ra để minh họa cách bạn có thể thực hiện việc này.

Trước tiên, thêm một số lớp bên trong để đặt bí danh cho Hoạt động hiện tại của bạn và đặt các lớp này vào danh sách chuỗi (cũng lưu ý rằng getSequencedActivityIntent() phương pháp mà tôi đã viết, bạn có thể thêm logic nâng cao hơn nếu bạn cần - có thể sử dụng HashMap để liên kết từng lớp trong chuỗi với một giá trị thẻ tùy ý?):

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
}

Đừng quên thêm các mục nhập của họ vào tệp AndroidManifest.xml của bạn (singleTop là tùy chọn - nó sẽ ngăn chặn cá thể Hoạt động trong ngăn xếp được tạo lại khi được đưa trở lại mặt trước):

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

Bây giờ, bất cứ khi nào bạn cần bắt đầu một phiên bản "hàng đầu" mới của Hoạt động, bạn có thể thực hiện một số việc như:

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

Và khi bạn cần quay trở lại một trong những ví dụ trong backstack bạn có thể làm:

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

2
2017-08-28 17:26





Bạn có thể lập chỉ mục các hoạt động của mình mà không phải lo lắng về việc xử lý tất cả chuỗi onActivityResults sử dụng một hoạt động siêu mà bạn mở rộng trong tất cả các hoạt động của bạn

Đây là một thực hiện (tôi đã không thử nghiệm nó) nhưng nếu bạn mở rộng SuperActivity này trong tất cả các hoạt động của bạn, bạn có thể gọi fallBackToActivity( int ) cho bất kỳ hoạt động nào sử dụng chỉ mục của nó và mỗi hoạt động hiện có một getIndex (). Bạn có thể sử dụng nó để dự phòng cho một chỉ mục tương đối như 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
2017-08-31 12:39





Bạn chỉ có thể giữ điều kiện trong bảng sao kê của mình nếu người dùng chọn mục này, hãy chuyển mục đích đến lớp B và nếu người dùng chọn mục đó, hãy chuyển mục đích đến lớp C


1
2017-08-23 11:18



Vấn đề là tất cả các hoạt động đều có cùng một lớp. - Warlock


Thêm vào thêm với ý định của bạn sẽ chỉ ra hoạt động cần làm. Ví dụ

    intent.putExtra("STATE", 1);

Và nhận giá trị này trong onCreate hoạt động của bạn.

  getIntent().getExtras()

1
2017-08-23 11:20



Imho cách duy nhất để sử dụng approache này là kết hợp nó với startActivityForResult / onActivityResult vv nhưng tôi hy vọng có thể có cách đơn giản hơn để làm điều đó. Tôi có thể có mười hoạt động như đã đề cập ở trên để onActivityResult sẽ được gọi đến nhiều lần ... - Warlock
Nếu vấn đề chính là cùng một lớp cho tất cả các hoạt động thì giải pháp có thể đơn giản. Tạo một lớp cơ sở sau đó mở rộng nó nhiều lần tùy theo nhu cầu của bạn và khởi tạo các lớp khác nhau. Nhưng tôi nghĩ đó là một cách tiếp cận kì lạ. Làm tốt hơn một máy trạng thái đơn giản và không khởi động lại hoạt động tương tự 100 lần ... - Dimanoid


Vì tôi hiểu Android chỉ nhắm mục tiêu vào lớp hoạt động chứ không phải là một hoạt động cụ thể. Vì vậy, tôi nghĩ rằng bạn sẽ không thể làm những gì bạn muốn bằng cách thêm một số cờ trên Intent.

Tôi nghĩ cách tiếp cận dễ nhất là tự mình thực hiện nó bằng một cái gì đó như thế này

a) Tạo một số singleton và có một thành viên trong đó trỏ đến hoạt động mà bạn muốn quay trở lại (ví dụ như hoạt động B). Có lẽ, bạn sẽ phải lưu trữ tất cả các hoạt động trong một số danh sách để có thể nhận được ví dụ về một số hoạt động được đưa ra trước đó.

b) Ghi đè lênResume cho tất cả các hoạt động và trong nó làm sau kiểm tra:

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

c) Ngay sau khi bạn cần phải quay trở lại từ E

SomeSingleton.setTargetActivity(B);
finish();

Điều này sẽ đóng hoạt động hàng đầu (là E) và gọi onResume về hoạt động D. Nó sẽ kiểm tra xem nó là mục tiêu. Nếu không thì nó sẽ đóng nó và hệ thống sẽ gọi onResume trên hoạt động C và cứ thế.


1
2017-08-29 21:06





Nếu bạn muốn sử dụng một cách tiếp cận bất thường, hoặc một số khó khăn một lần, bạn sẽ có nhiều vấn đề sau này. tôi nghĩ bạn có thể

Xác định lớp con trừu tượng / không trừu tượng của Hoạt động và xác định mọi thứ bạn muốn. Nếu các lớp khác là chính xác giống như lớp trên, vì vậy chỉ cần phân lớp từ nó và không làm gì hơn. Nhưng nếu các lớp (Hoạt động) có thể khác nhau, bạn có thể cung cấp các phương thức trừu tượng / không trừu tượng để xác định các khả năng bổ sung.

Vì thế

  • Bạn viết mã có thể sử dụng lại cho mọi hoạt động,
  • Bạn hành động bình thường để bạn có kết quả tốt
  • Bạn có thể kiểm soát tất cả mọi thứ chuyên về hoạt động của bạn
  • Bạn có thể kiểm soát ngăn xếp bằng tệp kê khai
  • và hơn thế nữa

để biết thông tin chi tiết, xem mã dưới đây:

Hoạt động gốc:

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

Hoạt động đầu tiên:

public class FirstActivity extends AbstractActivity {

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

Hoạt động thứ hai:

public class SecondActivity extends AbstractActivity {

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

tệp 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>

Tệp kê khai:

<?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
2017-09-01 04:17





Giải pháp tốt nhất và dễ nhất (cho đến nay) sẽ sử dụng Fragments và FragmentManager. Sau đó, hãy gắn thẻ từng Phân đoạn và sử dụng FragmentManager. Chỉ sử dụng Hoạt động có thể rất khó có kết quả gần như giống nhau.


0
2017-09-03 13:05



Tôi đã đề cập đến điều này trong câu trả lời của tôi! :) - Joe
Cách tiếp cận của bạn rất khác. Nhưng cảm ơn ý tưởng đó! ;-) - Warlock