부모 활동으로 올바르게 돌아가려면 어떻게해야합니까?


179

내 안드로이드 응용 프로그램에 2 개의 활동 (A 및 B)이 있으며 활동 A에서 활동 B로 가져 가려는 의도를 사용합니다. parent_activity 사용이 활성화되었습니다.

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

또한 UP 버튼을 제공하는 테마를 사용합니다.

따라서 액티비티를 호출 한 후 BI는 UP 버튼을 사용하여 액티비티 A로 돌아갈 수 있습니다. 문제는 응용 프로그램 이 액티비티 A 의 onCreate () 함수를 다시 호출하는 것처럼 보이고 이것이 필요한 동작이 아니라는 것입니다. 액티비티 B를 호출하기 전과 같은 방식으로 보이려면 액티비티 A가 필요합니다.

이것을 달성 할 수있는 방법이 있습니까?

미리 감사드립니다

편집하다:

활동 A에서 활동 B를 시작하는 코드를 작성하지 않았습니다. 이클립스에 의해 자동 생성 된 것으로 생각합니다.

클래스 B는 다음과 같습니다.

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

B에서 활동 A를 시작하기위한 코드를 게시하십시오.
user370305

내가 올바르게 이해하면 startActivityForResult ()를 사용하고 resultCode 또는 무언가를 반환 할 수 있습니다.
법률 Gimenez

태그 된 정답을 업데이트하십시오! 올바른 답변은 LorenzCK에서 온 것입니다-사용자가 아닙니다 ...! 이것을 올바른 것으로 태그하면 오해의 소지가 있으며 더 많은 프로그래머가 뒤로 탐색이 아닌 탐색을 잘못 이해합니다!
Zordid

여기에 오답이 너무 많아서 정리하는 데 도움을 줄 수 있습니까?
Zordid

@ashiaka-코드 디자인에 따라 정답이 업데이트됩니다.
user370305

답변:


334

launchModeAndroid 매니페스트에서 표준 으로 활동 A를 선언했습니다 . documentation 에 따르면 다음을 의미합니다.

시스템은 항상 대상 작업에서 활동의 새 인스턴스를 작성하고 의도를 라우팅합니다.

따라서 시스템은 onCreate작업 스택이 올바르게 처리 되더라도 활동 A (즉, 호출 ) 를 다시 작성해야 합니다.

이 문제를 해결하려면 A 속성 선언에 다음 속성을 추가하여 매니페스트를 변경해야합니다.

android:launchMode="singleTop"

참고 :finish() (이전의 솔루션으로 제안 된) 호출 은 종료중인 활동 B 인스턴스가 활동 A의 인스턴스 위에 존재 하는지 완전히 확신 하는 경우 에만 작동 합니다 .보다 복잡한 워크 플로우 (예 : 알림에서 활동 B 시작) 그렇지 않을 수 있으며 B에서 활동 A를 올바르게 시작해야합니다.


11
다음은 Android 문서의 설명입니다 . "표준"및 "singleTop"모드는 한 가지 측면에서 서로 다릅니다. "표준"활동에 대한 새로운 의도가있을 때마다 클래스의 새 인스턴스가 생성됩니다. 그 의도. 각 인스턴스는 단일 의도를 처리합니다. 유사하게, 새로운 의도를 처리하기 위해 "singleTop"활동의 새로운 인스턴스가 생성 될 수도 있습니다. 그러나 대상 작업에 이미 스택 맨 위에 활동의 기존 인스턴스가있는 경우 해당 인스턴스는 새 의도 (onNewIntent () 호출에서)를 수신합니다. 새 인스턴스가 작성되지 않습니다.
kpsfoo

참고에 따른 문서 것은 navigateUpFromSameTask(...) 추가해야한다 FLAG_ACTIVITY_CLEAR_TOPupIntent(경유 navigateUpTo(...)하는 (에 따라 같은 동작이 발생한다 이 가이드 )하지만 플래그가 설정되지 않습니다 - 따라서이 답변은 의미한다
Anigif

82

업데이트 된 답변 : 탐색 디자인

어떤 활동이 각 활동에 적합한 부모인지 선언해야합니다. 그렇게하면 시스템이 매니페스트 파일에서 논리적 상위 활동을 판별 할 수 있으므로 시스템은 Up과 같은 탐색 패턴을 용이하게합니다.

이를 위해서는 속성이있는 태그 활동에서 상위 활동을 선언해야합니다.

android:parentActivityName

처럼,

<!-- 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>

이 방법으로 선언 된 부모 활동을 사용하면 아래와 같이 적절한 부모까지 탐색 할 수 있습니다.

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

따라서이 NavUtils.navigateUpFromSameTask(this);메소드 를 호출 하면 현재 활동이 완료되고 적절한 상위 활동이 시작 (또는 재개)됩니다. 대상 상위 활동이 작업의 백 스택에있는 경우에 정의 된대로 전달됩니다 FLAG_ACTIVITY_CLEAR_TOP.

그리고 Up 버튼을 표시하려면 선언해야합니다. setDisplayHomeAsUpEnabled():

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

기존 답변 : (위로 탐색하지 않고 기본 뒤로 탐색)

활동 B에서 활동 A를 다시 시작하는 경우에만 발생합니다.

사용 startActivity().

대신 활동 A에서 활동 A를 사용하여 활동 B를 시작 하고 활동 A에서 startActivityForResult()대체하십시오 onActivtyResult().

이제 액티비티 B에서 finish()위로 버튼을 호출하십시오 . 이제 onActivityResult()활동 A를 다시 작성하지 않고 활동 A로 이동했습니다.


활동 B의 startActivity ()가 어디에서 호출되는지 모르겠습니다. 활동 B의 소스 코드를 게시했습니다.
ashiaka

18
코드 라인 NavUtils.navigateUpFromSameTask(this); 쓰기 대신 finish().
user370305

4
내비게이션 ( developer.android.com/design/patterns/navigation.html ) 에 대해 Google이 언급 finish()하거나 startActivityForResult()문서에 언급하지 않은 이유는 무엇 입니까?
wired00

이것은 힘든 해결 방법처럼 들립니다. @LorenzCK의 답변이 훨씬 더 나은 것 같습니다.
carmen_munich

NavUtils.navigateUpFromSameTask (this)를 사용해 주셔서 감사합니다. 큰 플러스! 일부 상황에서 부모 활동으로 돌아 가지 않는 finish ()를 대체하는 이와 같은 방법을 찾고 있습니다. finish ()는 본질적으로 반드시 상위 활동이 아닌 이전 활동으로 되돌아갑니다.
Hong

22

나는 똑같은 원치 않는 행동으로 이어지는 거의 동일한 설정을 가지고있었습니다. 나를 위해 이것은 효과가 있었다 : Manifest.xml내 응용 프로그램 의 활동 A에 다음 속성을 추가하십시오 .

android:launchMode="singleTask"

자세한 내용은 이 기사 를 참조하십시오 .


1
내 관점에서 문제에 대한 올바른 해결책입니다. 작업이 작업 스택에있는 경우 finish ()를 호출 한 것처럼 작동합니다. 그렇지 않은 경우 작성되어 시작됩니다.
Johan

5
매번 불필요하게 새 작업을 생성하므로 올바른 방법이 아닙니다. 대신 launchMode = "singleTop"를 사용해야합니다.
kpsfoo

19

오래된 질문이지만 위젯 에서 Activity B딥 링크 한 이후 이전의 모든 답변이 저에게 적합하지 않은 또 다른 (가장 깨끗하고 최상의 방법) 솔루션이 있습니다.

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 ]

또한 참조 : https://speakerdeck.com/jgilfelt/this-way-up-implementing-effective-navigation-on-android


7

이를 달성하는 더 좋은 방법은 다음 두 가지를 사용하는 것입니다.

NavUtils.navigateUpFromSameTask(this);

이제이 작업을 수행하려면 활동 A에 상위 활동 B가 있다는 매니페스트 파일 상태가 필요합니다. 상위 활동에는 아무것도 필요하지 않습니다. 버전 4 이상에서는 추가 노력없이 멋진 뒤로 화살표가 나타납니다 (이것은 작은 코드로 더 낮은 버전에서도 수행 할 수 있습니다. 아래에 넣을 것입니다).이 데이터를 매니페스트-> 응용 프로그램 탭에서 설정할 수 있습니다 GUI에서 (부모 활동 이름까지 아래로 스크롤하여 손으로 입력)

지원 노드 :

버전 4 이하의 버전을 지원하려면 메타 데이터도 포함해야합니다. 활동, 추가-> 메타 데이터, 이름 = android.support.PARENT_ACTIVITY 및 값 = your.full.activity.name을 마우스 오른쪽 단추로 클릭하십시오.

낮은 버전에서도 멋진 화살표를 얻으려면 :

getSupportActionBar().setDisplayHomeAsUpEnabled(true);

이 모든 기능을 사용하려면 라이브러리 버전 7 지원이 필요하지만 그만한 가치가 있습니다!


5

나를 위해 일한 것은 추가했습니다.

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

TheRelevantActivity.java예상대로 지금은 노력하고 있습니다

그리고 예를 추가하는 것을 잊지 마십시오 :

getSupportActionbar.setDisplayHomeAsUpEnabled(true);onCreate()방법


4

나는 시도 android:launchMode="singleTask"했지만 도움이되지 않았다. 나를 위해 일했다.android:launchMode="singleInstance"


부모 활동에 android : launchMode = "singleInstance"를 추가하면 문제가 해결되었습니다
emir

4

@LorenCK의 답변에 추가, 변경

NavUtils.navigateUpFromSameTask(this);

다른 활동에서 활동을 시작할 수 있고 다른 앱에서 시작한 작업의 일부가 될 수있는 경우 아래 코드로

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

그러면 새 작업이 시작되고 Min SDK 버전 <= 15 이하와 같이 매니페스트에서 정의 할 수있는 활동의 상위 활동이 시작됩니다.

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

또는 parentActivityName15보다 큰 경우 사용


참고 : parentActivityNameSDK> 15를 선언하지 않으면 임의의 충돌이 발생합니다
Sourabh

3

부모 활동 이름이 나쁜 안드로이드 5.0을 사용할 때 비슷한 문제가 발생했습니다.

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

부모 활동 이름에서 com.example.myfirstapp를 제거하고 제대로 작동했습니다.


2

속성을 사용하여 활동 매니페스트 정보에 추가

android:launchMode="singleTask"

나를 위해 잘 작동합니다


1
완료 흐름은 다음과 같습니다. @Override public boolean onOptionsItemSelected (MenuItem item) {switch (item.getItemId ()) {case android.R.id.home : NavUtils.navigateUpFromSameTask (this); true를 반환; } return super.onOptionsItemSelected (item); }
Pravesh Kumar

매니페스트에 추가 <activity android : name = ". MainActivity"android : label = "@ string / title_activity_main"> </ activity> <activity android : name = ". CreateEventActivity"android : label = "@ string / title_activity_create_event"android : launchMode = "singleTask"android : parentActivityName = ". MainActivity"> <meta-data android : name = "android.support.PARENT_ACTIVITY"android : value = ". MainActivity"/> </ activity>
Pravesh Kumar

2

자바 클래스에서 :-

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

    getSupportActionBar().setTitle("Snapdeal");

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

매니페스트에서 :-

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

그것은 당신을 도울 것입니다


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

뒤로 언론처럼


1

이 시도:

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

내 매니페스트에 들어가서 android:launchMode="singleTop"활동에 추가 하면 나에게 속임수가되었습니다.

Up툴바 의 버튼을 누른 후 Android가 이전 활동의 새 인스턴스를 작성하지 않기를 원했기 때문에 내 문제를 해결 했습니다. 탐색 계층 구조를 올라갈 때 이전 활동의 기존 인스턴스를 대신 사용하려고했습니다.

참조 : android : launchMode


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.