Intent complex data transfer of Android

Introduction to this section:

In the previous section, we learned some basic uses of Intent, including the seven attributes of Intent, explicit Intent and implicit Intent, and how to customize implicit Intent, and finally provided you with some commonly used system Intents! And this section will explain to you the problem of Intent passing data~Okay, let’s start this section~


1. Intent transfers simple data

Remember how we learned how to pass simple data between two Activities in the Activity?

That is, you can directly store data by calling the putExtra() method of the Intent, and then call getXxxExtra to obtain the corresponding type of data after getting the Intent; if you pass more than one, you can use the Bundle object as a container, and store the data in the Bundle first by calling putXxx of the Bundle In the Bundle, then call the putExtras() method of the Intent to store the Bundle in the Intent, and then after getting the Intent, call getExtras() to get the Bundle container, and then call its getXXX to get the corresponding data! In addition, data storage is somewhat similar to Map's <key, value>!


2. Intent transfer array

Hey, ordinary types are fine, but what if it's an array? The solution is as follows:

Write to the array :

bd.putStringArray("StringArray", new String[]{"Haha", "haha"}); 
// StringArray can be replaced with other data types, such as int, float, etc...

Read the array :

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

3. Intent transfer collection

Well, the array is very simple, so let's pass the collection~ This is a little more complicated, and we will deal with it according to the situation:


1) List<basic data type or String>

Write to collection:

intent.putStringArrayListExtra(name, value)
intent.putIntegerArrayListExtra(name, value)

Read collection:

intent.getStringArrayListExtra(name)
intent.getIntegerArrayListExtra(name)

2)List< Object>

Forcibly convert the list into a Serializable type, and then pass it in (Bundle can be used as a medium)

Write to collection:

putExtras(key, (Serializable)list)

Read collection:

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

PS: The Object class needs to implement the Serializable interface


3) Map<String, Object>, or more complex

The solution is: put a List on the outer layer

// Pass more complex parameters 
Map<String, Object> map1 = new HashMap<String, Object>();   
map1.put("key1", "value1");   
map1.put("key2", "value2") ;   
List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();   
list.add(map1);   

Intent intent = new Intent();   
intent.setClass(MainActivity.this,ComplexActivity. class);   
Bundle bundle = new Bundle();   

//A list must be defined to pass the ArrayList<Object> to be passed in the budnle, this is a necessary   
ArrayList bundlelist = new ArrayList();    
bundlelist.add(list) ;    
bundle.putParcelableArrayList("list",bundlelist);   
intent.putExtras(bundle);                 
startActivity(intent);

4. Intent transfer object

There are two ways to transfer objects: convert the object to a Json string or use Serializable, Parcelable serialization. It is not recommended to use Android's built-in Json parser. You can use fastjson or Gson third-party library!


1) Convert the object to a Json string

Example of Gson parsing:

Model:

public class Book{
    private int id;
    private String title;
    //...
}

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

data input:

Book book=new Book();
book.setTitle("Java编程思想");
Author author=new Author();
author.setId(1);
author.setName("Bruce Eckel");
book.setAuthor(author);
Intent intent=new Intent(this,SecondActivity.class);
intent.putExtra("book",new Gson().toJson(book));
startActivity(intent);

read data:

String bookJson=getIntent().getStringExtra("book");
Book book=new Gson().fromJson(bookJson,Book.class);
Log.d(TAG,"book title->"+book.getTitle());
Log.d(TAG,"book author name->"+book.getAuthor().getName());

2) Use Serializable, Parcelable to serialize objects


1.Serializable implementation:

①Business Bean implementation: Serializable interface, write getter and setter methods
②Intent passes in the object instance by calling putExtra(String name, Serializable value) Of course, if there are multiple objects, we can also first Bundle.putSerializable(x,x );
③The new Activity calls the getSerializableExtra() method to obtain the object instance: eg:Product pd = (Product) getIntent().getSerializableExtra("Product"); ④Call the
object get method to obtain the corresponding parameters


2.Parcelable implementation:

General process:

①The business bean inherits the Parcelable interface, rewrite the writeToParcel method, and serialize your object into a Parcel object; ②Rewrite the
describeContents method, the content interface description, and return 0 by default
③Instantiate the static internal object CREATOR to implement the interface Parcelable.Creator
④In the same style, pass in the object instance through the putExtra() method of Intent. Of course, if there are multiple objects, we can put them in the Bundle first. Bundle.putParcelable(x,x) and then Intent.putExtras()

Some explanations:

Map your object to a Parcel object through writeToParcel, and then map the Parcel object to your object through createFromParcel. Parcel can also be regarded as a stream, write objects into the stream through writeToParcel, and read objects from the stream through createFromParcel, but this process requires you to implement, so the order of writing and reading must be consistent.

Code example implementing the Parcelable interface:

//Internal Description Interface,You do not need to manage  
@Override  
public int describeContents() {  
     return 0;  
}  
       
      
 
@Override  
public void writeToParcel(Parcel parcel, int flags){  
    parcel.writeString(bookName);  
    parcel.writeString(author);  
    parcel.writeInt(publishTime);  
}  
      

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

Android Studio generates the Parcleable plugin:

The Intellij/Andriod Studio plugin android-parcelable-intellij-plugin can directly generate the Parcleable interface code as long as ALT+Insert.

In addition: Parcelable objects are widely used in Android, and it is very cumbersome to implement the Parcable interface. You can use a third-party open source framework: Parceler. Because of the Maven problem, I haven't tried it yet.

Reference address: [Android Parcelable automatically generated]

3. Comparison of two serialization methods:

Comparison of the two:

  • 1) When using memory, Parcelable has higher performance than Serializable, so it is recommended to use Parcelable.
  • 2) Serializable will generate a large number of temporary variables during serialization, which will cause frequent GC.
  • 3) Parcelable cannot be used in the case of storing data on disk, because Parcelable cannot guarantee the persistence of data well in the case of changes in the outside world. Although Serializable is less efficient, it is recommended to use Serializable at this time.

5. Intent transfer Bitmap

Bitmap implements the Parcelable interface by default, just pass it directly

Implementation code:

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

6. It is inconvenient to pass around, directly define global data

If it is to transfer simple data, there is such a requirement, Activity1 -> Activity2 -> Activity3 -> Activity4, you want to transfer a certain data from Activity to Activity4, how to break it, one page by one?

Obviously unscientific, isn't it? If you want a certain data to be available anywhere, you can consider using the  Application global object !

The Android system creates an Application object when each program is running, and only one will be created, so Application is a class in the singleton mode, and the life cycle of the Application object is the longest in the entire program. Period is equal to the lifetime of this program. If you want to store some more static values ​​(fixed or changeable), if you want to use Application, you need a custom class to implement the Application class, and tell the system to instantiate our custom Application instead of the system default , and this step is to add the name attribute to our application tag in AndroidManifest.xml !

Key part code:

1) Custom Application class:

class MyApp extends Application {
    private String myState;
    public String getState(){
        return myState;
    }
    public void setState(String s){
        myState = s;
    }
}

2) Declaration in AndroidManifest.xml:

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

3) Call where needed:

class Blah extends Activity {
    @Override
    public void onCreate(Bundle b){
        ...
    MyApp appState = ((MyApp)getApplicationContext());
    String state = appState.getState();
        ...
    }
}

high-quality writing

: The Application global object can be obtained at any location.

Applicaiton is a component of the system, and it also has its own life cycle. We can get the Application object in onCraete. Post the modified code!

class MyApp extends Application {
    private String myState;
    private static MyApp instance;
    
    public static MyApp getInstance(){
        return instance;
    }
    
    
    public String getState(){
        return myState;
    }
    public void setState(String s){
        myState = s;
    }
    
    @Override
    public void onCreate(){
        onCreate();
        instance = this;
    }
 
}

Then we can call directly anywhere: MyApp.getInstance() to get the global object of Application!


Precautions:

The Application object exists in memory, so it may be killed by the system, such as this scenario:

We stored the user account in the application in Activity1, then got the user account in Activity2, and displayed it!

If we click the home button and wait for N long time, the system kills our app in order to reclaim the memory. At this time, we reopen the app. It is amazing at this time, and we return to the Activity2 page, but if you go to obtain the user account in Application at this time, the program will report NullPointerException and then crash~

The above crash occurs because the Application object is newly created. You may think that the App is restarted, but it is not. It is just to create a new Application, and then start the Activity when the user left last time, thus creating Apps don't have the illusion of being killed! So if it is more important data, it is recommended that you still perform localization. In addition, when using data, you must check the value of the variable for non-nullness! Another point is: not only Application variables, but also singleton objects and public static variables~


7. Pass parameters in singleton mode

The above Application is based on singletons. The characteristic of the singleton pattern is that it can ensure that there is only one instance of a class in the system. This can be easily achieved, setting parameters in A and directly accessing them in B. This is the most efficient of several methods.

Sample code: (the code comes from the Internet~)

① Define a singleton class :

public class XclSingleton   
{   
    //Singleton mode instance   
    private static XclSingleton instance = null;   
      
    //synchronized is used for thread safety to prevent multiple threads from creating instances at the same time   
    public synchronized static XclSingleton getInstance(){   
        if(instance == null){   
            instance = new XclSingleton();   
        }      
        return instance;   
    }      
      
    final HashMap<String, Object> mMap;   
    private XclSingleton()   
    {   
        mMap = new HashMap<String,Object>();   
    }   
      
    public void put(String key,Object value){   
        mMap.put (key, value);   
    }   
       
    public Object get(String key)  
    {  
        return mMap.get(key);  
    }  
      
} 

②Set parameters:

XclSingleton.getInstance().put("key1", "value1");  
XclSingleton.getInstance().put("key2", "value2");  

Guess you like

Origin blog.csdn.net/leyang0910/article/details/131449334