Làm thế nào tôi có thể trở lại hoạt động chính xác?


179

Tôi có 2 hoạt động (A và B) trong ứng dụng Android của mình và tôi sử dụng ý định chuyển từ hoạt động A sang hoạt động B. Việc sử dụng Parent_activity được bật:

 <activity
        android:name=".B"
        android:label="B" >
        <meta-data
            android:name="android.support.PARENT_ACTIVITY"
            android:value="com.example.app_name.A" />
  </activity>

Tôi cũng sử dụng một chủ đề cung cấp nút LÊN.

Vì vậy, sau khi tôi gọi hoạt động BI có thể sử dụng nút LÊN để quay lại hoạt động A. Vấn đề là ứng dụng dường như gọi lại chức năng onCreate () của hoạt động A và đây không phải là hành vi tôi cần. Tôi cần hoạt động A để trông giống như trước khi tôi gọi hoạt động B.

Có cách nào để đạt được điều này?

Cảm ơn trước

BIÊN TẬP:

Tôi đã không viết bất kỳ mã nào để bắt đầu hoạt động B từ hoạt động A. Tôi nghĩ rằng nó được tự động tạo ra bởi nhật thực.

Lớp B trông như:

    @Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_b);
    getActionBar().setDisplayHomeAsUpEnabled(true);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.activity_b, menu);
    return true;
}


@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case android.R.id.home:
            NavUtils.navigateUpFromSameTask(this);
            return true;
    }
    return super.onOptionsItemSelected(item);
}

Gửi mã cho bạn, để bắt đầu Hoạt động A từ B ..
user370305

Nếu tôi hiểu bạn đúng, bạn có thể sử dụng startActivityForResult () và trả về một resultCode hoặc một cái gì đó.
Luật Gimenez

Vui lòng cập nhật câu trả lời đúng được gắn thẻ của bạn! Câu trả lời ĐÚNG đến từ LorenzCK - không phải từ người dùng ......! Gắn thẻ này là chính xác là sai lệch và thậm chí nhiều lập trình viên hiểu nhầm điều hướng hơn là điều hướng trở lại!
Zordid

Gee, rất nhiều câu trả lời sai ở đây, bạn có thể vui lòng giúp đỡ trong việc này không ...?
Zordid

@ashiaka - Câu trả lời đúng theo thiết kế mã của bạn được cập nhật.
dùng370305

Câu trả lời:


334

Bạn đã khai báo hoạt động A với tiêu chuẩn launchModetrong bảng kê khai Android. Theo tài liệu , điều đó có nghĩa như sau:

Hệ thống luôn tạo ra một thể hiện mới của hoạt động trong tác vụ đích và định hướng ý định đến nó.

Do đó, hệ thống buộc phải tạo lại hoạt động A (tức là gọi onCreate) ngay cả khi ngăn xếp tác vụ được xử lý chính xác.

Để khắc phục sự cố này, bạn cần thay đổi tệp kê khai, thêm thuộc tính sau vào khai báo hoạt động A:

android:launchMode="singleTop"

Lưu ý: việc gọi finish()(như được đề xuất là giải pháp trước đây) chỉ hoạt động khi bạn hoàn toàn chắc chắn rằng hoạt động B mà bạn đang chấm dứt cuộc sống bên trên một thể hiện của hoạt động A. Trong các quy trình công việc phức tạp hơn (ví dụ: khởi chạy hoạt động B từ thông báo) đây có thể không phải là trường hợp và bạn phải khởi chạy chính xác hoạt động A từ B.


11
Dưới đây là lời giải thích từ các tài liệu Android, Chế độ "tiêu chuẩn" và "đơn lẻ" khác nhau chỉ ở một khía cạnh: Mỗi khi có ý định mới cho hoạt động "tiêu chuẩn", một phiên bản mới của lớp được tạo để đáp ứng ý định đó Mỗi trường hợp xử lý một mục đích duy nhất. Tương tự, một phiên bản mới của hoạt động "singleTop" cũng có thể được tạo để xử lý mục đích mới. Tuy nhiên, nếu tác vụ đích đã có một phiên bản hiện có của hoạt động ở đầu ngăn xếp của nó, thì thể hiện đó sẽ nhận được mục đích mới (trong lệnh gọi onNewIntent ()); một trường hợp mới không được tạo.
kpsfoo

Lưu ý rằng theo tài liệu navigateUpFromSameTask(...) nên được thêm FLAG_ACTIVITY_CLEAR_TOPvào upIntent(thông qua navigateUpTo(...)đó sẽ dẫn đến hành vi tương tự (theo hướng dẫn này ), nhưng cờ không bao giờ được đặt - và do đó câu trả lời này có ý nghĩa
Anigif

82

Cập nhật câu trả lời: Thiết kế dẫn đường

Bạn phải khai báo hoạt động nào là cha mẹ thích hợp cho từng hoạt động. Làm như vậy cho phép hệ thống tạo điều kiện cho các mẫu điều hướng như Up vì hệ thống có thể xác định hoạt động cha mẹ logic từ tệp kê khai.

Vì vậy, bạn phải khai báo Hoạt động cha mẹ trong thẻ Hoạt động với thuộc tính

android:parentActivityName

Giống,

<!-- The main/home activity (it has no parent activity) -->
    <activity
        android:name="com.example.app_name.A" ...>
        ...
    </activity>
    <!-- A child of the main activity -->
    <activity
        android:name=".B"
        android:label="B"
        android:parentActivityName="com.example.app_name.A" >
        <!-- Parent activity meta-data to support 4.0 and lower -->
        <meta-data
            android:name="android.support.PARENT_ACTIVITY"
            android:value="com.example.app_name.A" />
    </activity>

Với hoạt động chính được khai báo theo cách này, bạn có thể điều hướng đến phụ huynh thích hợp như bên dưới,

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
    // Respond to the action bar's Up/Home button
    case android.R.id.home:
        NavUtils.navigateUpFromSameTask(this);
        return true;
    }
    return super.onOptionsItemSelected(item);
}

Vì vậy, khi bạn gọi NavUtils.navigateUpFromSameTask(this);phương thức này, nó kết thúc hoạt động hiện tại và bắt đầu (hoặc tiếp tục lại) hoạt động cha mẹ thích hợp. Nếu hoạt động cha mẹ đích nằm trong ngăn xếp ngược của tác vụ, nó sẽ được chuyển tiếp như được định nghĩa bởi FLAG_ACTIVITY_CLEAR_TOP.

Và để hiển thị nút Up, bạn phải khai báo setDisplayHomeAsUpEnabled():

@Override
public void onCreate(Bundle savedInstanceState) {
    ...
    getActionBar().setDisplayHomeAsUpEnabled(true);
}

Câu trả lời cũ: (Không có Điều hướng lên, Điều hướng quay lại mặc định)

Nó chỉ xảy ra nếu bạn bắt đầu lại Hoạt động A từ Hoạt động B.

Sử dụng startActivity().

Thay vì điều này từ Hoạt động A bắt đầu Hoạt động B sử dụng startActivityForResult()và ghi đè onActivtyResult()trong Hoạt động A.

Bây giờ trong Hoạt động B chỉ cần gọi finish()vào nút Lên. Vì vậy, bây giờ bạn đã hướng đến Hoạt động A onActivityResult()mà không tạo lại Hoạt động A nữa ..


Tôi không biết startActivity () trong hoạt động B được gọi ở đâu. Tôi đã đăng mã nguồn của hoạt động B ...
ashiaka

18
Thay vì NavUtils.navigateUpFromSameTask(this); viết dòng mã finish().
user370305

4
Nó đặt ra câu hỏi, tại sao Google không đề cập bất cứ điều gì về finish()hoặc startActivityForResult()trong tài liệu của họ về Điều hướng ( developer.android.com/design/potypes/navlation.html )?
dây00

Điều này nghe có vẻ như một cách giải quyết khó khăn. Câu trả lời @LorenzCK có vẻ tốt hơn nhiều.
carmen_munich

Cảm ơn rất nhiều vì đã sử dụng NavUtils.navigateUpFromSameTask (cái này). Điểm cộng lớn! Tôi đã tìm kiếm một phương thức như thế này để thay thế kết thúc () không quay lại hoạt động cha mẹ trong một số trường hợp. finish () về cơ bản là quay trở lại hoạt động trước đó không nhất thiết là hoạt động mẹ.
Hồng

22

Tôi đã có khá nhiều thiết lập tương tự dẫn đến cùng một hành vi không mong muốn. Đối với tôi điều này đã hoạt động: thêm thuộc tính sau vào hoạt động A trong Manifest.xmlứng dụng của tôi:

android:launchMode="singleTask"

Xem bài viết này để giải thích thêm.


1
Theo quan điểm của tôi, giải pháp chính xác cho vấn đề. Điều này sẽ hoạt động giống như nếu bạn gọi finish () nếu Activity tồn tại trong ngăn xếp tác vụ. Nếu đó không phải là trường hợp, nó sẽ được tạo và bắt đầu.
Johan

5
Đây không phải là cách chính xác vì nó sẽ tạo ra một nhiệm vụ mới một cách không cần thiết mỗi lần, thay vào đó bạn nên sử dụng launchMode = "singleTop".
kpsfoo

19

Mặc dù là một câu hỏi cũ, đây là một giải pháp khác (imho là sạch nhất và tốt nhất) vì tất cả các câu trả lời trước đó không hiệu quả với tôi vì tôi đã liên kết sâu Hoạt động B từ một Widget .

public void navigateUp() {
final Intent upIntent = NavUtils.getParentActivityIntent(this);
if (NavUtils.shouldUpRecreateTask(this, upIntent) || isTaskRoot()) {
    Log.v(logTag, "Recreate back stack");
        TaskStackBuilder.create(this).addNextIntentWithParentStack(upIntent).startActivities();
  } else {
    NavUtils.navigateUpTo(this, upIntent);
  }
}

[ https://stackoverflow.com/a/31350642/570168 ]

Nhưng cũng xem: https://speakerdeck.com/jgilfelt/this-way-up-im Hiệning-hiệu quả-navulation-on-android


7

Một cách tốt hơn để đạt được điều này là sử dụng hai điều: gọi:

NavUtils.navigateUpFromSameTask(this);

Bây giờ, để làm việc này, bạn cần phải có tệp kê khai của bạn nói rằng hoạt động A có hoạt động cha mẹ B. Hoạt động chính không cần bất cứ điều gì. Trong phiên bản 4 trở lên, bạn sẽ nhận được một mũi tên quay lại đẹp mà không cần nỗ lực thêm (điều này có thể được thực hiện trên các phiên bản thấp hơn với một ít mã, tôi sẽ đặt nó bên dưới) Bạn có thể đặt dữ liệu này trong tab ứng dụng-> trong GUI (cuộn xuống tên hoạt động mẹ và đặt nó bằng tay)

Nút hỗ trợ:

nếu bạn muốn hỗ trợ phiên bản bên dưới phiên bản 4, bạn cũng cần bao gồm siêu dữ liệu. nhấp chuột phải vào hoạt động, thêm-> dữ liệu meta, tên = android.support.PARENT_ACTIVITY và value = your.full.activity.name

để có được mũi tên đẹp trong các phiên bản thấp hơn:

getSupportActionBar().setDisplayHomeAsUpEnabled(true);

xin lưu ý rằng bạn sẽ cần thư viện hỗ trợ phiên bản 7 để mọi thứ hoạt động, nhưng nó rất đáng giá!


5

Những gì làm việc cho tôi đã được thêm vào:

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        switch (item.getItemId()) {
            case android.R.id.home:
                onBackPressed();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

    @Override
    public void onBackPressed() {
        finish();
    }

đến TheRelevantActivity.javavà bây giờ nó đang hoạt động như mong đợi

và vâng đừng quên thêm:

getSupportActionbar.setDisplayHomeAsUpEnabled(true);trong onCreate()phương pháp


4

Tôi đã cố gắng android:launchMode="singleTask", nhưng nó không giúp được gì. Làm việc cho tôi bằng cách sử dụngandroid:launchMode="singleInstance"


Thêm android: launchMode = "singleInstance" vào hoạt động của cha mẹ đã giải quyết vấn đề cho tôi
emir

4

Thêm vào câu trả lời của @ LorenCK, thay đổi

NavUtils.navigateUpFromSameTask(this);

theo mã bên dưới nếu hoạt động của bạn có thể được bắt đầu từ một hoạt động khác và điều này có thể trở thành một phần của nhiệm vụ được bắt đầu bởi một số ứng dụng khác

Intent upIntent = NavUtils.getParentActivityIntent(this);
if (NavUtils.shouldUpRecreateTask(this, upIntent)) {
    TaskStackBuilder.create(this)
            .addNextIntentWithParentStack(upIntent)
            .startActivities();
} else {
    NavUtils.navigateUpTo(this, upIntent);
}

Điều này sẽ bắt đầu một nhiệm vụ mới và bắt đầu Hoạt động chính của Hoạt động mà bạn có thể xác định trong Bản kê khai như bên dưới phiên bản SDK tối thiểu <= 15

<meta-data
        android:name="android.support.PARENT_ACTIVITY"
        android:value="com.example.app_name.A" />

Hoặc sử dụng parentActivityNamenếu nó> 15


Lưu ý: Không khai báo parentActivityNamecho SDK> 15 nếu không, nó sẽ cung cấp cho bạn một số sự cố ngẫu nhiên
Sourabh

3

Tôi gặp vấn đề tương tự khi sử dụng Android 5.0 với tên hoạt động cha mẹ không tốt

<activity
        android:name=".DisplayMessageActivity"
        android:label="@string/title_activity_display_message"
        android:parentActivityName=".MainActivity" >
        <meta-data
            android:name="android.support.PARENT_ACTIVITY"
            android:value="com.example.myfirstapp.MainActivity" />
    </activity>

Tôi đã xóa com.example.myfirstapp khỏi tên hoạt động chính và nó hoạt động đúng


2

Thêm vào thông tin bảng kê khai hoạt động của bạn với thuộc tính

android:launchMode="singleTask"

đang làm việc tốt cho tôi


1
Luồng hoàn thành giống như vậy @Override boolean công khai onOptionsItemSelected (mục MenuItem) {switch (item.getItemId ()) {case android.R.id.home: NavUtils.navigateUpFromSameTask (this); trả lại đúng sự thật; } return super.onOptionsItemSelected (item); }
Pravesh Kumar

Thêm vào bảng kê khai của bạn <Activity android: name = ". MainActivity" android: nhãn = "@ string / title_activity_main"> </ Activity> <Activity android: name = ". CreateEventActivity" android: nhãn = "@ string / title_activity_create_event : launchMode = "singleTask" android: ParentActivityName = ". MainActivity"> <meta-data android: name = "android.support.PARENT_ACTIVITY" android: value = ". MainActivity" /> </ Activity>
Pravesh Kumar

2

Trong lớp Java: -

    toolbar = (Toolbar) findViewById(R.id.apptool_bar);
    setSupportActionBar(toolbar);

    getSupportActionBar().setTitle("Snapdeal");

    getSupportActionBar().setHomeButtonEnabled(true);
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);

Trong Bản kê khai: -

<activity
            android:name=".SubActivity"
            android:label="@string/title_activity_sub"
            android:theme="@style/AppTheme" >
            <meta-data android:name="android.support.PARENT_ACTIVITY" android:value=".MainActivity"></meta-data>
    </activity>

Nó sẽ giúp bạn


1
    @Override
public boolean onOptionsItemSelected(MenuItem item) {
   switch (item.getItemId()) {
// Respond to the action bar's Up/Home button
    case android.R.id.home:
        finish();
        return true;
}
return super.onOptionsItemSelected(item);

như một báo chí trở lại


1

thử cái này:

Intent intent;
@Override
public void onCreate(Bundle savedInstanceState) {
    intent = getIntent();   
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_b);
    getActionBar().setDisplayHomeAsUpEnabled(true);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.activity_b, menu);
    return true;
}  

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case android.R.id.home:
            NavUtils.navigateUpTo(this,intent);
            return true;
    }
    return super.onOptionsItemSelected(item);
}

0

Đi vào bảng kê khai của tôi và thêm android:launchMode="singleTop"vào hoạt động đã giúp tôi.

Điều này đặc biệt giải quyết vấn đề của tôi vì tôi không muốn Android tạo một phiên bản mới của hoạt động trước đó sau khi nhấn Upnút trên thanh công cụ - thay vào đó tôi muốn sử dụng phiên bản hiện tại của hoạt động trước đó khi tôi đi lên phân cấp điều hướng.

Tham khảo: android: launchMode


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.