활동이 들어옵니다


1. Activity, Window, View의 관계

그렇습니다. 원래는 이들 간의 관계를 이해하고 싶었지만, 손이 많이 가면서 호출 프로세스를 살펴보기 시작했습니다. 한 시간 동안 아주 작은 부분만 이해했습니다. 당연히 소스 코드를 배우기 위해 바닥까지 가는 사람들은 모두 아직 그 수준에 도달하지 못한 위대한 대가들입니다. 다음은 제가 참고한 정보를 요약한 것이며 소스 코드의 다음 부분을 읽어보겠습니다. 만약 실수가 있으면 자유롭게 지적해주세요! 요약 다이어그램은 아래에 게시됩니다.

1.jpg

프로세스 분석: Activity는 startActivity를 호출한 후 마지막으로 연결 메서드를 호출한 다음 PolicyManager에서 Ipolicy 인터페이스를 구현하고 정책 개체를 구현한 다음 makenewwindow를 호출합니다. (컨텍스트) 메소드, 이 메소드는 PhoneWindow 객체를 반환하고 PhoneWindow Window의 서브클래스입니다. 이 PhoneWindow에는 모든 애플리케이션 윈도우의 루트 View, 즉 View의 보스인 DecorView의 내부 클래스가 있습니다. 활동 표시 여부를 직접 제어합니다(이전 드라이버의 원래 단어 인용...). 그러면 내부에 LinearLayout이 있고 내부에 두 개의 FrameLayout이 각각 ActionBar 및 CustomView를 설치하는 데 사용되며 레이아웃은 에 의해 로드됩니다. setContentView()는 이 CustomView에 배치됩니다!

이 세 가지의 관계를 요약해 보겠습니다. 터무니없는 비유를 사용해 보겠습니다. 우리는 이것을 각각 화가, 캔버스, 붓으로 그린 ​​것의 세 가지 범주라고 부를 수 있습니다. 화가는 브러시(LayoutInflater.infalte)로 패턴을 그린 다음 캔버스(addView)에 그립니다! 마지막으로 표시됩니다(setContentView)


2. Activity, Task 및 Back Stack의 몇 가지 개념

그런 다음 Task 및 Back Stack이라는 두 가지 용어를 포함하는 Android의 Activity 관리 메커니즘을 이해해 보겠습니다!

개념 분석:

우리 앱은 일반적으로 여러 활동으로 구성되며 Android는 Task 개념을 제공합니다. 이는 여러 관련 활동을 수집한 다음 활동을 점프하고 반환하는 것입니다! 물론 이 Task는 단지 프레임워크 레이어의 개념이자 Android에서 Task를 구현하는 데이터 구조는 Back Stack입니다! 스택의 데이터 구조는 다들 잘 알고 계시리라 믿습니다. Java에도 Stack이라는 클래스가 있습니다! 스택에는 다음과 같은 특징이 있습니다.

선입선출(LIFO)에서 일반적으로 사용되는 작업은 푸시(Push) 및 팝(Pop)입니다. 맨 위를 스택의 맨 아래라고 합니다

.

그리고 Android 스택에도 위와 같은 특징이 있습니다. 이것이 활동을 관리하는 방법입니다.

새 활동으로 전환하면 해당 활동이 스택에 푸시되어 스택의 맨 위에 있게 됩니다! 사용자가 뒤로 버튼을 클릭하면 스택 맨 위에 있는 액티비티가 튀어나오고, 뒤따르는 액티비티가 스택 맨 위로 올라옵니다.

공식 문서에 제공된 흐름도를 살펴보겠습니다.

2.png

프로세스 분석:

애플리케이션에는 A1, A2, A3 세 가지 활동이 있습니다. 사용자가 런처나 홈 화면에서 애플리케이션 아이콘을 클릭하면, 메인 A1을 시작한 다음 A1이 A2를 시작하고 A2가 A3을 시작합니다. 이때 스택에는 세 가지 활동이 있으며 이 세 가지 활동이 포함됩니다. 동일한 태스크(Task)에서 사용자가 리턴키를 누르면 A3가 팝업되고, 다시 리턴키를 누르면 스택에는 A1과 A2만 남게 된다. A2를 팝업하면 A1만 스택에 남습니다. 계속해서 Return 키를 누르고 A1을 팝업하면 작업이 제거됩니다. 즉, 프로그램이 종료됩니다.

그러다가 공식 문서에서 다른 두 장의 사진을 보고 호기심에 설명을 다시 읽고 그룹에 있는 사람들과 논의했습니다.

3.png

그리고 다음과 같은 설명이 있습니다. 그는 다음과 같이 결론지었습니다.

4.png

Task는 활동의 모음이며 이는 실제로 활동을 저장하는 데 사용됩니다. 동시에 하나의 스택만 앞에 있고 나머지는 배경에 있습니다! 스택은 어떻게 생겼나요?

답변: 아이콘을 클릭하여 홈 화면을 통해 새 앱을 열면 새 작업이 생성됩니다! 예: 주소록 앱 아이콘을 클릭하여 앱을 엽니다. 이때 새 스택 1이 생성되고 새로 생성된 활동이 추가됩니다. 주소록 APP이지만 이때 새로운 스택이 생성되지 않고 스택 1에 계속 추가됩니다. Android는 사용자 경험 접근 방식을 장려합니다. 즉, 서로 다른 애플리케이션 간에 전환하면 사용자가 동일한 애플리케이션인 것처럼 느낄 수 있습니다. 공식적으로는 Seamless라고 불리는 매우 일관된 사용자 경험입니다! ——————이 때 홈 버튼을 클릭하여 홈 화면으로 돌아가고 스택 1이 배경으로 들어가면 다음 두 가지 작업이 수행될 수 있습니다.

1) 메뉴 버튼(사각형 버튼)을 클릭하고, 클릭하여 프로그램을 연 다음 스택 1이 전경으로 돌아갑니다! 또는 홈 화면의 주소록 아이콘을 클릭하여 APP를 엽니다. 이때 새 스택이 생성되지 않고 스택 1이 전경으로 돌아갑니다.
2) 이때 다른 아이콘을 클릭하여 새 앱을 열면 이때 새 스택 2가 생성되고 스택 2가 전경으로 나타납니다. 그리고 스택 1은 계속해서 백그라운드에 남아 있습니다.

3) 나중에도 마찬가지입니다.



3.작업 관리

1) 문서 번역:

자, 문서의 ManagingTasks부터 시작하여 문서화를 계속해 보겠습니다. 대략적인 번역은 다음과 같습니다.

1) 문서 번역

Continue with 문서, 문서의 ManagingTasks부터 시작하여 번역은 다음과 같습니다:

위에서 언급했듯이 Android는 새로 성공적으로 시작된 활동을 동일한 작업에 추가하고 "선입선출" 방식으로 여러 작업을 관리합니다. Back Stack을 사용하면 사용자는 활동이 태스크와 상호 작용하는 방식이나 활동이 백 스택에 존재하는 방식에 대해 걱정할 필요가 없습니다! 어쩌면 당신은 이 일반적인 관리 스타일을 바꾸고 싶을 수도 있습니다. 예를 들어 활동 중 하나를 새 작업에서 관리하려고 합니다. 또는 특정 활동만 인스턴스화하거나 사용자가 작업을 떠날 때 루트 활동을 제외한 작업의 모든 활동을 정리하고 싶을 수도 있습니다. AndroidManifest.xml을 수정하면 이러한 작업과 그 이상의 작업을 수행할 수 있습니다. < Activity >는 특별히 식별된 Intent를 코드의 startActivity()에 전달하여 쉽게 구현할 수 있습니다. 활동 관리.

< 활동 >에서 사용할 수 있는 속성은 다음과 같습니다. clearTaskOnLaunch

    alwaysRetainTaskState
  • FinishOnTaskLaunch
  • 사용할 수 있는 주요 인텐트 플래그는 다음과 같습니다:
  • FLAG_ACTIVITY_NEW_TASK
  • FLAG_ACTIVITY_CLEAR_TOP
  • FLAG_ACTIVITY_SINGLE_ TOP

자, 사용법을 하나씩 소개해볼까요? :

    2) taskAffinity 및 AllowTaskReparenting
  • 기본적으로 애플리케이션의 모든 활동에는 Affinity
  • 가 있어 동일한 작업에 속하게 됩니다. 동일한 작업에 있는지 여부를 나타내는 표시로 이해할 수 있습니다. 그러나 각 활동은 통과할 수 있습니다. <activity>의 taskAffinity 속성은 별도의 Affinity를 설정합니다. 다양한 애플리케이션의 활동은 동일한 선호도를 공유할 수 있으며 동일한 애플리케이션의 다양한 활동은 공유할 수 있습니다. 다른 선호도로 설정할 수도 있습니다. Affinity 속성은 2가지 상황에서 작동합니다.
  • 1) 활동을 시작하는 Intent 객체에
  • FLAG_ACTIVITY_NEW_TASK
  • 태그가 포함된 경우: startActivity()에 전달된 Intent 객체에 FLAG_ACTIVITY_NEW_TASK 태그가 포함되어 있으면 시스템은 시작해야 하는 활동에 대해 현재 활동과 다른 작업을 찾습니다. 시작될 활동의 Affinity 속성이 모든 현재 작업의 Affinity 속성과 다른 경우 시스템은 해당 Affinity 속성을 사용하여 새 작업을 생성하고 새로 생성된 작업 스택에 시작할 활동을 푸시합니다. 그렇지 않으면 활동이 시작됩니다. 동일한 스택의 Affinity 속성으로 푸시됩니다. 2)
  • allowTaskReparenting
속성이 true로 설정되었습니다. 활동의 AllowTaskReparenting 속성이 true인 경우 동일한 선호도를 사용하여 하나의 작업(Task1)에서 다른 작업(Task2)으로 이동할 수 있습니다(Task2가 포그라운드로 전환될 때). .apk 파일에 사용자 관점에서 여러 "애플리케이션"이 포함되어 있는 경우 해당 활동에 서로 다른 선호도 값을 할당해야 할 수도 있습니다.

3) launchMode:

발사 모드 연구의 핵심인 네 가지 선택 값에 대해 아래에서 자세히 설명하겠습니다! standard(기본값), singleTop, singleTask, singleInstance


4) 스택 지우기

사용자가 오랫동안 Task를 떠나는 경우(현재 작업이 백그라운드) 시스템은 작업의 스택 맨 아래에 있는 활동을 제외한 모든 활동을 지웁니다. . 이런 방식으로 사용자가 Task로 돌아오면 해당 Task의 원래 Activity만 남습니다. 다음 속성을 수정하여 이 행동을 바꾸세요!

alwaysRetainTaskState: 스택 맨 아래에 있는 액티비티의 이 속성을 true로 설정하면 위와 같은 상황이 발생하지 않습니다. 작업의 모든 활동은 오랫동안 저장됩니다.

clearTaskOnLaunch스택 하단에 있는 활동의 이 속성이 true로 설정된 경우 사용자가 작업을 종료하면 그런 다음 스택 맨 아래에 있는 활동만 남을 때까지 작업 스택의 활동이 지워집니다. 이 상황은 다음과 일치합니다. AlwaysRetainTaskState의 반대입니다. 사용자가 잠시 나가도 작업은 초기 상태로 돌아갑니다. (스택의 맨 아래에 있는 활동만 남습니다.)

finishOnTaskLaunch는clearTaskOnLaunch와 유사하지만 단일 활동에서만 작동합니다. 전체 Task가 아닌 Operation을 수행합니다. 스택 맨 아래에 있는 활동을 포함하여 모든 활동을 종료할 수 있습니다. true로 설정되면 현재 활동은 현재 세션 동안 작업의 일부로만 존재합니다. 사용자가 활동을 종료하고 돌아오면 해당 활동은 존재하지 않습니다.


4. 활동의 4가지 로딩 모드에 대한 자세한 설명:

다음으로 4가지 로딩 모드에 대해 자세히 설명하겠습니다. standard(기본값), singleTop, singleTask, singleInstance 인터넷에 접속했을 때 시작 모드를 설명하는 사진과 텍스트가 포함된 기사를 본 적이 있어서 더 쉬웠을 것 같아요. 여기에서 배워봅시다. 다음:

원본 링크: 활동 시작 모드에 대한 자세한 그래픽 및 텍스트 설명: Standard, SingleTop, SingleTask 및 SingleInstance

원문 영어 텍스트: Android 활동의 시작 모드 이해: Standard, SingleTop, SingleTask 및 SingleInstance로딩 모드에 대한 자세한 설명도 있습니다. Android에서 활동의 네 가지 시작 모드 및 taskAffinity 속성에 대한 자세한 설명

먼저 요약 그림을 살펴보겠습니다.

5.png

모드에 대한 자세한 설명:


표준 모드:

표준 시작 모드. 이는 활동의 기본 시작 모드이기도 합니다. 이 모드에서 시작된 활동은 여러 번 인스턴스화될 수 있습니다. 즉, 활동의 여러 인스턴스가 동일한 작업에 존재할 수 있으며 각 인스턴스는 인텐트 개체를 처리합니다. 활동 A의 시작 모드가 표준이고 A가 이미 시작된 경우 A에서 활동 A를 다시 시작합니다. 즉, startActivity(new Intent(this, A.class))를 호출하면 A의 인스턴스가 맨 위에서 다시 시작됩니다. 즉, 스택의 현재 상태는 A-->A입니다.

6.jpg

7.jpg


singleTop 모드:

singleTop 모드에서 시작된 Activity 인스턴스가 이미 작업 스택 상단에 있는 경우, 그런 다음 이 Activity가 다시 시작되면 새 인스턴스가 생성되지 않지만 스택 상단의 인스턴스가 재사용됩니다. 그리고 인스턴스의 onNewIntent() 메서드가 호출되어 Intent 개체를 이 인스턴스에 전달합니다. 예를 들어 A의 시작 모드가 SingleTop이고 A의 인스턴스가 스택 상단에 이미 존재하는 경우 그런 다음 startActivity(new Intent(this, A.class))를 호출하여 A를 시작하면, A의 인스턴스는 다시 생성되지 않지만 원본 인스턴스가 재사용되고 원본 인스턴스의 onNewIntent() 메서드가 호출됩니다. 이때 작업 스택에는 여전히 A의 인스턴스가 있습니다. 활동 인스턴스가 SingleTop 모드에서 시작된 경우 작업 스택에 이미 존재하지만 스택의 맨 위에 있지 않은 경우 해당 동작은 표준 모드와 동일하며 여러 인스턴스가 생성됩니다.

8.jpg


singleTask 모드:

시스템에서는 하나의 활동 인스턴스만 허용됩니다. 시스템에 이미 인스턴스가 있는 경우 이 인스턴스를 보유하는 작업은 맨 위로 이동되고 인텐트는 onNewIntent()를 통해 전송됩니다. 그렇지 않은 경우 새 활동이 생성되어 적절한 작업에 배치됩니다.

9.jpg

공식 문서에 언급된 문제:

시스템은 새 작업을 생성하고 이 활동을 새 작업의 루트로 인스턴스화합니다. taskAffinity:

10.jpg

11.jpg

을 사용한 후 taskAffinity를 설정해야 합니다.

singleInstance 모드

는 시스템이 어떤 작업에서 활동을 시작하든 상관없이 하나의 활동 인스턴스만 생성하여 새 작업 스택의 맨 위에 추가하도록 보장합니다. 즉, 이 인스턴스에서 시작된 다른 활동은 자동으로 다른 작업에서 실행됩니다. 활동 인스턴스가 다시 시작되면 기존 작업과 인스턴스가 재사용됩니다. 이 인스턴스는 호출됩니다. onNewIntent() 메서드는 Intent 인스턴스를 인스턴스에 전달합니다. 싱글태스크와 동일 시스템에는 동시에 하나의 활동 인스턴스만 있습니다.

12.jpg


5. 액티비티 보충자료

액티비티에 대해 아직 언급되지 않은 내용이 있을 수 있으니 이곳에 자리를 예약해두고, 부족한 부분은 여기서 보충하도록 하겠습니다! 우선, 그룹 친구인 Zhuhai Kun이 오픈소스 중국의 활동 관리 수업을 게시하자고 제안했습니다. 여기, 누구나 직접 사용할 수 있습니다. 프로젝트 중~

1)开源中國客户端Activity管理类:

package net.oschina.app;

import java.util.Stack;

import android.app.Activity;
import android.app.ActivityManager;
import android .content.Context;


공개 클래스 AppManager {

비공개 정적 Stack<Activity> ActivityStack;
비공개 정적 AppManager 인스턴스;

비공개 AppManager(){}
/**
* 단일 인스턴스
*/
공개 정적 AppManager getAppManager(){
if(instance==null){
인스턴스=new AppManager();
}
return instance;
}
/**
* 스택에 활동 추가
*/
public void addActivity(Activity activity){
if(activityStack==null){
activityStack=new Stack<Activity>();
}
activityStack .add(activity);
}
/**
* 현재 활동 가져오기(스택에 마지막으로 푸시된 활동)
*/
public Activity currentActivity(){
Activity activity=activityStack.lastElement();
return activity;
}
/**
* 현재 활동 종료(스택에 마지막으로 푸시된 활동)
*/
public void finishActivity(){
Activity activity=activityStack.lastElement();
finishActivity(activity);
}
/**
* 지정된 활동 종료
*/
public void finishActivity(Activity activity){
if(activity!=null) {
activityStack.remove(activity);
activity.finish();
activity=null;
}
}
/**
* 지정된 클래스 이름의 활동 종료
*/
public void finishActivity(Class<?> cls){
for( 활동 활동 : activityStack) {
if(activity.getClass().equals(cls) ){
finishActivity(activity);
}
}
}
/**
* 모든 활동 종료
*/
public void finishAllActivity(){
for(int i=0, size=activityStack.size(); 나는 < 크기; i++){
            if (null != activityStack.get(i)){
            activityStack.get(i).finish();
           }
    }
activityStack.clear();
}
/**
*애플리케이션 종료
* /
public void AppExit(Context context) {
try {
finishAllActivity();
ActivityManager activityMgr= (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
ActivityMgr.restartPackage(context.getPackageName());
System.exit(0);
} catch (Exception e) { }
}
}

이 섹션 요약:

좋아, 이 섹션은 여기까지입니다 , 상황이 조금 씁쓸하고 이해하기 어렵습니다. 지금은 작업의 전체 일정을 요약해 보겠습니다. 관련 작업:

  • 이전 작업을 배경으로 전환하려면 홈 버튼을 누르세요.
  • 홈 버튼을 길게 누르면 최근 실행한 작업 목록이 표시됩니다.
  • 런처 또는 홈 화면에서 앱 아이콘을 클릭하여 작업을 엽니다. 또는 기존 작업을 포그라운드로 예약합니다.
  • singleTask 모드에서 활동을 시작하면 적절한 작업이 이미 존재하는지 확인하기 위해 시스템을 검색합니다. 해당 작업은 포그라운드로 예약되어 재사용됩니다. 일. 이 작업에서 시작할 활동의 인스턴스가 이미 있는 경우 이 인스턴스 위의 모든 활동을 지우고 이 인스턴스를 사용자에게 표시합니다. 이 기존 태스크에서 시작할 활동의 인스턴스가 없으면 이 태스크의 맨 위에서 인스턴스가 시작됩니다. 이 태스크가 없으면 새 태스크가 시작되고 이 새 태스크에서 이 SingleTask 모드 활동의 인스턴스가 시작됩니다.
  • singleInstance의 활동을 시작하면 시스템에 이 활동의 ​​인스턴스가 이미 있는지 검색합니다. 존재하는 경우 이 인스턴스가 있는 작업이 포그라운드로 예약되고 이 활동의 ​​인스턴스가 시작됩니다. 재사용(작업에 이 활동만 있음). 존재하지 않는 경우 새 작업이 시작되고 이 단일 인스턴스 모드 활동의 인스턴스가 이 새 작업에서 시작됩니다.

이 섹션은 여기까지입니다. 작업 및 활동 로드 모드에 대한 내용은 여전히 ​​매우 복잡하며 이 글을 작성하는 단계를 게시하겠습니다. 직접 참고자료를 확인해 보세요~


참고자료: