인텐트의 복잡한 데이터 전달


이 섹션 소개:

이전 섹션에서 우리는 Intent의 몇 가지 기본 사용법을 배웠고 Intent의 7가지 속성, 명시적 Intent 및 Intent에 대해 배웠습니다. 암시적 인텐트, 암시적 인텐트를 사용자 정의하는 방법, 그리고 마지막으로 일반적으로 사용되는 시스템 인텐트를 제공합니다! 이번 섹션에서는 인텐트 전달 데이터의 문제에 대해 설명하겠습니다~좋아, 이번 섹션부터 시작하겠습니다~


1. 인텐트는 간단한 데이터를 전달합니다

Activity A 방식에서 두 가지 활동을 통해 서로 통신하는 방법을 배웠다는 것을 기억하세요. 간단한 데이터를 전달하려면?

1.png

Intent의 putExtra() 메소드를 호출하여 데이터를 직접 저장할 수 있으며, Intent를 가져온 후 getXxxExtra를 호출할 수 있습니다. 해당 유형의 데이터, 여러 개가 전달되면 Bundle 객체를 컨테이너로 사용하고 먼저 Bundle의 putXxx를 호출하여 데이터를 전송할 수 있습니다. Bundle에 저장한 후 Intent의 putExtras() 메소드를 호출하여 Bundle을 Intent에 저장하고 Intent를 얻은 후, 번들 컨테이너를 얻으려면 getExtras()를 호출하고 해당 데이터를 얻으려면 getXXX를 호출하세요! 게다가 데이터 저장은 Map의 <키, 값>과 다소 유사합니다!


2. 인텐트가 배열을 통과함

헤헤 일반형도 문제없지만 배열이면 어떨까요? 해결책은 다음과 같습니다:

Write into the array:

bd.putStringArray("StringArray", new String[]{"haha","haha"});
//StringArray는 다음으로 대체될 수 있습니다. int, float 등과 같은 다른 데이터 유형...

배열 읽기:

String[] str = bd.getStringArray("StringArray")

3 인텐트는 컬렉션을 전달합니다

음, 배열 아주 간단하니 다시 컬렉션을 전달해 볼까요~ 이건 좀 더 복잡하고 상황에 따라 처리됩니다:


1) List<기본 데이터 유형 또는 문자열>

Write the 컬렉션:

intent.putStringArrayListExtra(이름, 값)
intent.putIntegerArrayListExtra(이름, 값)

컬렉션 읽기:

intent.getStringArrayListExtra(이름)
intent.getIntegerArrayListExtra(이름 )

2) List< Object> ;

목록을 직렬화 가능한 유형으로 만든 다음 전달합니다(번들은 매체로 사용할 수 있음)

컬렉션 작성:

putExtras(key, (Serialize)list )

컬렉션 읽기:

(List<Object>) getIntent().getSerialized(key)

PS: Object 클래스는 직렬화 가능 인터페이스를 구현해야 합니다.


3) Map 또는 더 복잡한

해결책은 다음과 같습니다. 외부 레이어에 목록 넣기

//Pass 더 복잡한 매개변수
Map map1 = new HashMap()
map1.put("key1", "value1");
List> list = new ArrayList>()
list.add(map1);

Intent 의도 = new Intent(); MainActivity.this ,ComplexActivity.class);
Bundle Bundle = new Bundle();

//Burnle에서 전달해야 하는 ArrayList<Object>를 전달하려면 목록을 정의해야 합니다.
ArrayList Bundlelist = new ArrayList () ;
bundlelist.add(list);
bundle.putParcelableArrayList("list",bundlelist);
intent.putExtras(bundle); 객체를 전달하는 방법에는 객체를 Json 문자열로 변환하거나 직렬화하는 두 가지 유형이 있습니다. 직렬화 가능 및 Parcelable을 통해 Android에 내장된 Json 파서를 사용하지 않는 것이 좋습니다. fastjson 또는 Gson 타사 라이브러리를 사용할 수 있습니다!


1) 객체를 Json 문자열로 변환

Gson 구문 분석 예:

Model:

public class Author{       private int id          private String name;        /...

}

public class Author{ private int id;

private String name;
//...
}



쓰기 데이터:



Book book=new Book();
book.setTitle ("Java 프로그래밍 생각");
저자 작성자=new Author();
author.setId(1);
author.setName("Bruce Eckel");

book.setAuthor(저자);Intent 의도=새 의도(this,SecondActivity) .class);intent.putExtra("book",new Gson().toJson(book));

startActivity(intent);

读取数据:

String bookJson=getIntent().getStringExtra("book");
Book book=new Gson().fromJson(bookJson,Book.class);
Log.d(TAG," 책 제목->"+book.getTitle());
Log.d(TAG,"책 저자 이름->"+book.getAuthor().getName());

2) Serialized, Parcelable을 사용하여 객체 직렬화


1. 직렬화 가능 구현:

① 비즈니스 Bean 구현: 직렬화 가능 인터페이스, getter 및 setter 메소드 작성
②Intent 호출 putExtra(문자열 이름, 직렬화 가능 값) 전달 객체 인스턴스 물론, 여러 객체가 있는 경우 먼저 Bundle.putSerialized(x,x);
③새 Activity가 getSerializedExtra() 메서드를 호출하여 객체 인스턴스를 얻을 수도 있습니다. 예:Product pd = (Product) getIntent().getSerializedExtra("Product");
4해당 매개변수를 얻기 위해 객체 get 메소드를 호출합니다


2. Parcelable 구현:

일반 프로세스:

① 비즈니스 Bean은 Parcelable 인터페이스를 상속하고 writeToParcel 메소드를 재정의하며 객체를 Parcel 객체로 직렬화합니다.
② explainContents 메소드, 컨텐츠 인터페이스 설명을 다시 작성하고 기본적으로 0을 반환합니다.
③ 정적 내부 객체 CREATOR를 인스턴스화합니다. Parcelable 인터페이스를 구현하세요
4같은 방식으로 Intent의 putExtra() 메소드를 통해 객체 인스턴스가 전달됩니다. 물론 객체가 여러 개인 경우 먼저 할 수 있습니다. Bundle.putParcelable(x,x)에 넣은 다음 Intent.putExtras()

몇 가지 설명:

writeToParcel을 통해 개체를 Parcel 개체에 매핑한 다음 createFromParcel을 통해 Parcel 개체를 매핑합니다. 당신의 대상이 되십시오. Parcel을 스트림으로 생각하고 writeToParcel을 통해 스트림에 개체를 쓸 수도 있습니다. createFromParcel을 통해 스트림에서 객체를 읽지만 이 프로세스에서는 이를 구현해야 하므로 작성하세요. 순서와 읽는 순서가 일관되어야 합니다.

Parcelable 인터페이스 구현을 위한 코드 예:

//내부 설명 인터페이스,관리할 필요가 없습니다.  
}  
       
      
 
@Override  
public void writeToParcel(Parcel parcel, int flags){  
    parcel.writeString(bookName);  
    parcel.writeString(작성자);  
    parcel.writeInt(publishTime);  
}  
      

public static final Parcelable.Creator<Book> CREATOR = 새 Creator<Book>() {  
    @Override  
    public Book[] newArray(int size) {  
        새 책[크기] 반환;  
    }  
          
    @Override  
    public Book createFromParcel(Parcel source) {  
        Book mBook = new Book();    
        mBook.bookName = source.readString();   
        mBook.author = source.readString();    
        mBook.publishTime = source.readInt();   
        mBook 반환;  
    }  
};

Android Studio에서는 Parcleable 플러그인을 생성합니다.

Intellij/Andriod Studio 플러그인 android-parcelable-intellij-plugin ALT+Insert를 누르면 Parcleable 인터페이스 코드를 직접 생성할 수 있습니다.

또한, Parcelable 객체는 Android에서 널리 사용되며 Parcable 인터페이스를 구현하는 것은 매우 번거로울 수 있습니다. 타사 오픈 소스 프레임워크: Parceler, Maven 문제 때문에 아직 시도하지 않았습니다.

참조 주소:[안드로이드의 Parcelable 자동 생성]

3. 두 가지 직렬화 방법 비교:

두 가지 방법 비교:

  • 1) 메모리를 사용할 경우 Parcelable이 Serialized High보다 성능이 좋으므로 Parcelable을 사용하는 것이 좋습니다.
  • 2) 직렬화 가능은 직렬화 중에 많은 수의 임시 변수를 생성하므로 GC가 자주 발생합니다.
  • 3) Parcelable은 데이터의 무결성을 보장할 수 없기 때문에 데이터를 디스크에 저장할 때 Parcelable을 사용할 수 없습니다. 외부 세계의 변화에도 불구하고 지속성. 직렬화 가능은 덜 효율적이지만 현재로서는 여전히 직렬화 가능을 사용하는 것이 좋습니다.

5. Intent는 Bitmap을 전달합니다.

bitmap은 기본적으로 Parcelable 인터페이스를 구현하므로 직접 전달할 수 있습니다.

구현 코드:

Bitmap bitmap = null;
Intentintent = new Intent();
Bundle Bundle = new Bundle();
bundle.putParcelable("bitmap", bitmap);
intent.putExtra("bundle", Bundle);

6. 전역 데이터를 직접 정의하는 것이 불편합니다.

간단한 데이터를 전달하는 경우 Activity1 -> Activity2 -> Activity의 특정 데이터를 Activity4로 전달하고 싶습니다. 어떻게 페이지에서 페이지로 전달하시겠습니까?

물론 비과학적이겠죠? 특정 데이터를 어디서나 사용할 수 있게 하려면 Application 전역 객체 사용을 고려해 보세요!

안드로이드 시스템은 각 프로그램이 실행될 때 Application 개체를 생성하며 하나만 생성되므로 Application 싱글톤 패턴의 클래스로, 전체 프로그램 중 Application 객체의 수명이 가장 길다. 기간은 본 프로그램의 수명주기와 동일합니다. 더 많은 정적 값(고정 및 변경 불가능, 변경 가능)을 저장하려는 경우 애플리케이션에는 Application 클래스를 구현하고 인스턴스화되는 사용자 정의 애플리케이션임을 시스템에 알리기 위해 사용자 정의 클래스가 필요합니다. 시스템 기본값 대신 이 단계에서는 AndroidManifest.xml의 애플리케이션 태그에 name 속성 을 추가합니다.

코드의 주요 부분:

1) 사용자 정의 애플리케이션 클래스:

class MyApp 확장 애플리케이션 {
private String myState;
public String getState(){
return myState;
}
public void setState(문자열 s){
myState = s;
}
}

2) AndroidManifest.xml의 명령문:

<application android:name=".MyApp" android:icon="@drawable/ icon "
android:label="@string/app_name">

3) 필요한 곳에 전화하세요:

class Blah 확장 활동 {
@Override
public void onCreate(Bundle b){
.. .
MyApp appState = ((MyApp)getApplicationContext());
문자열 상태 = appState.getState();
...
}
}

고화질 쓰기 방법

: 애플리케이션 전역 개체는 어느 위치에서나 얻을 수 있습니다.


Applicaiton은 시스템의 구성 요소이며 자체 수명 주기도 있습니다. onCraete에서 이를 얻을 수 있습니다. 응용 프로그램 개체입니다. 수정된 코드를 게시하세요! YClass MyApp 확장 애플리케이션 {

Private String Mystate;
Private Static MyApp Instance; @Override
public void onCreate(){
onCreate();
인스턴스 = this;

그런 다음 어디에서나 MyApp.getInstance()를 직접 호출하여 애플리케이션의 전역 개체를 가져올 수 있습니다!


참고:

Application 개체는 메모리에 존재하며 다음 시나리오와 같이 시스템에 의해 종료될 수 있습니다.

사용자 계정을 Activity1의 애플리케이션에 저장한 다음 사용자 계정을 Activity2를 표시해 보세요!

홈 버튼을 클릭한 후 N을 오래 기다린 후 시스템은 메모리를 회수하기 위해 앱을 종료합니다. 이때 우리는 다시 이 앱을 열면 이때는 마법처럼 보입니다. Activity2 페이지로 돌아가지만 이때 애플리케이션을 다시 받으면 프로그램 내 사용자 계정에서 NullPointerException이 발생하고 Crash가 발생합니다~

위의 Crash가 발생하는 이유는 Application 객체가 새로 생성되었기 때문이라고 생각하시면 됩니다. 실제로는 그렇지 않습니다. 새 애플리케이션을 만든 다음 사용자가 마지막으로 떠날 때 활동을 시작하여 앱을 만듭니다. 죽는다는 환상은 없습니다! 따라서 더 중요한 데이터라면 현지화하여 활용하는 것이 좋습니다. 변수 값이 null이 아닌지 확인해야 합니다! 또 다른 요점은 이것이 애플리케이션 변수뿐만 아니라 싱글톤 개체 및 공용 정적 변수에도 적용된다는 것입니다. 이렇게 됩니다~


7. 싱글톤 모드 매개변수 전달

위 애플리케이션은 싱글톤을 기반으로 하며 시스템에 클래스의 인스턴스가 하나만 있음을 보장할 수 있다는 것입니다. A에서 매개변수를 설정하고 B에서 직접 액세스하면 매우 쉽게 달성할 수 있습니다. 이는 여러 가지 방법 중 가장 효율적입니다.

예제 코드: (코드는 인터넷에서 제공됩니다~)

단일 케이스 클래스 정의:

public classized static Instance == NULL) {
Instance = New XClsingleton ()
}
Return Instance;









mmap = 새로운 해시맵 & LT; 문자열, 개체 및 GT()
}
}
public void put(문자열 키, 개체 값){

{
}
 
}



②매개변수 설정:


XclSingleton.getInstance(). put("key1", "value1");
XclSingleton.getInstance().put("key2", "value2" ; 애플리케이션 및 싱글톤 패턴을 사용하여 매개변수를 전달하세요! 데이터 전송에 있어서 모두에게 편리함을 가져다 줄 것이라 믿습니다. 감사합니다~