This is the sixth day of my participation in the August Text Challenge.More challenges in August
Android Activity communication mode
It is a common way for activities to communicate with each other. For example, page transitions need to carry information. For example, parameters on the first page need to be displayed on the second page.
Bundle delivery
Meaning: Encapsulates data in a Bundle object and carries it around with the Intent.
Pseudo code
Pass basic data types and String types
// Pass Bundle Bundle = new Bundle(); bundle.putString("name", "Jack"); bundle.putInt("id", 1); Intent intent = new Intent(this, MainActivity2.class); intent.putExtras(bundle); startActivity(intent); Bundle = getIntent().getextras (); String name = bundle.getString("name"); int id = bundle.getInt("id"); Log.d("===", "name:" + name + " _ id:" + id);Copy the code
Transfer object
Serialize the object before passing it; otherwise, an error will be reported.
One thing to note
Objects passed through serialization are transmitted and received with the same content but with different reference addresses. That is, if the received object is changed and its value is changed, the original object passed to the page is not affected
- What is serialization?
Serialization is used to convert object data into byte streams for easy transmission. So we need to serialize the object when passing it, and then deserialize it at the receiving end to restore the object.
- How to serialize
The Serializable and Parcelable
Serializable: The entity class directly implements the Serializable interface
import java.io.Serializable; public class Student implements Serializable { private int id; private String name; public Student() { } public Student(int id, String name) { this.id = id; this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; }} // send Student Student = new Student(1, "Jack"); Bundle bundle = new Bundle(); bundle.putSerializable("student", student); Intent intent = new Intent(this, MainActivity2.class); intent.putExtras(bundle); startActivity(intent); Bundle = getIntent().getextras (); Student student = (Student) bundle.getSerializable("student"); Log.d("===", "person:"+student.getName());Copy the code
Parcelable: Implements interfaces and implements methods
import android.os.Parcel; import android.os.Parcelable; public class Student implements Parcelable { private int id; private String name; public Student() { } public Student(int id, String name) { this.id = id; this.name = name; } protected Student(Parcel in) { id = in.readInt(); name = in.readString(); } public static final Creator<Student> CREATOR = new Creator<Student>() { @Override public Student createFromParcel(Parcel in) { return new Student(in); } @Override public Student[] newArray(int size) { return new Student[size]; }}; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(id); dest.writeString(name); }} // send Student Student = new Student(1, "Jack"); Bundle bundle = new Bundle(); bundle.putParcelable("student", student); Intent intent = new Intent(this, MainActivity2.class); intent.putExtras(bundle); startActivity(intent); Bundle = getIntent().getextras (); Student student = (Student) bundle.getParcelable("student"); Log.d("===", "person:"+student.getName());Copy the code
From the code point of view, Serializable is Java and Parcelable is Android. Parcelable is an optimized product of Android. Under the same conditions, Parcelable can reduce the memory footprint significantly.
Two, broadcast transmission
Broadcast is one of the four components of Android. It is a global listener that can listen to broadcast messages from other apps or systems.
You can also pass data between activities, but it’s a bit overkill.
External storage
If there is A large amount of data, the data can be temporarily stored in the memory card in an Activity, and then retrieved from the memory card after jumping to B Activity.
Static variables
Store data in static variables, assign values to static variables in A Activity, get data from static variables after jumping to B Activity, and then recycle the static variables.
V. Application transfer
A custom application class that temporarily stores variables, usually not used for code cleanliness.
Six, ARouter
Arouter also has some methods for passing messages. Things like withObject, withString, etc
Look at their internal methods
/**
* Set object value, the value will be convert to string by 'Fastjson'
*
* @param key a String, or null
* @param value a Object, or null
* @return current
*/
public Postcard withObject(@Nullable String key, @Nullable Object value) {
serializationService = ARouter.getInstance().navigation(SerializationService.class);
mBundle.putString(key, serializationService.object2Json(value));
return this;
}
/**
* Inserts a String value into the mapping of this Bundle, replacing
* any existing value for the given key. Either key or value may be null.
*
* @param key a String, or null
* @param value a String, or null
* @return current
*/
public Postcard withString(@Nullable String key, @Nullable String value) {
mBundle.putString(key, value);
return this;
}
Copy the code
Bundles are also used for transmission. The principle is the same as that of bundles.
Seven, EventBus
In the use of transfer data Bundle, when large amount of data (more than 1 m), will be thrown TransactionTooLargeException anomalies.
This problem can be easily solved using EventBus.
1. The EventBus profile
EventBus is an event publish-subscribe bus for Android, developed by GreenRobot, that makes it easy to transfer data.
2. Three components of EventBus
- Event: An Event that can be of any type. EventBus is notified globally based on the Event type.
- The Subscriber: Event subscribers, before EventBus 3.0 we had to define the methods that start with onEvent, onEvent, onEventMainThread, onEventBackgroundThread, and onEventAsync, After 3.0, the name of the event processing method can be arbitrary, but you need to add the annotation @subscribe and specify the thread model. The default is POSTING.
- Publisher: An event Publisher that can publish events in any thread. In general, you can get an EventBus Object using eventbus.getDefault () and then call the POST (Object) method.
3. EventBus four threading models
- POSTING: By default, the thread representing the event handler is in the same thread as the thread POSTING the event.
- MAIN: The thread that represents the event handler is in the MAIN thread (UI) thread, so time-consuming operations cannot be performed here.
- BACKGROUND: Indicates that the event handler thread is in the BACKGROUND thread and therefore cannot perform UI operations. If the thread publishing the event is the main thread (the UI thread), the event handler will start a background thread, and if the thread publishing the event is a background thread, the event handler will use this thread.
- ASYNC: indicates that no matter which thread is used to publish the event, the event handler will always create a new child thread to run and also cannot perform UI operations.
4. The EventBus
4.1 Importing Dependencies
Implementation 'org. Greenrobot: eventbus: 3.1.1'Copy the code
4.2 Create an entity class as the object to be passed
public class MessageInfo { private String message; public MessageInfo(String message) { this.message = message; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; }}Copy the code
4.3 Defining receive events
The Activity:
public class MainActivity extends AppCompatActivity { private TextView tv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv = findViewById(R.id.tv); EventBus.getDefault().register(this); // initialize EventBus} @override protected void onDestroy() {super.ondestroy (); EventBus.getDefault().unregister(this); @subscribe (threadMode = threadmode.main) public void getMessage(MessageInfo MessageInfo) {Subscribe(threadMode = threadmode.main) public void getMessage(MessageInfo MessageInfo) { tv.setText(messageInfo.getMessage()); Toast.maketext (this, "received message:" + messageInfo.getMessage(), toast.length_short).show(); } public void GoMain2Activity(View view) { Intent intent = new Intent(this, Main2Activity.class); startActivity(intent); }}Copy the code
Layout:
<? The XML version = "1.0" encoding = "utf-8"? > <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="GoMain2Activity" android:text="Hello World!" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" /> <TextView android:id="@+id/tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text=""/> </android.support.constraint.ConstraintLayout>Copy the code
4.4 Defining sending Events
The Activity:
public class Main2Activity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main2); Public void publishMessage(view view) {eventbus.getDefault ().post(new) MessageInfo(" Little Leo ")); }}Copy the code
Layout:
<? The XML version = "1.0" encoding = "utf-8"? > <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".Main2Activity"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" android:onClick="publishMessage"/> </android.support.constraint.ConstraintLayout>Copy the code
4.5 Viscous events
The so-called sticky event refers to the event that the subscriber can still receive after the event is sent. There are two things that need to be changed when using sticky events. One is a place to subscribe to events, where we register to listen for sticky events in the Activity we opened first: add the sticky = true attribute
Subscribe(threadMode = threadmode. MAIN, sticky = true) public void getMessage(MessageInfo messageInfo) { tv.setText(messageInfo.getMessage()); Toast.maketext (this, "received message:" + messageInfo.getMessage(), toast.length_short).show(); }Copy the code
To send an event using postSticky:
/** * @param view */ public void publishMessage(view view) {eventbus.getDefault ().poststicky (new MessageInfo(" Little Leo ")); Intent intent = new Intent(this, MainActivity.class); startActivity(intent); }Copy the code
4.6 priority
In the Subscribe annotation there are three arguments, two of which we used above. Here we use the third argument, priority. It is used to specify the priority of the subscription method and is an integer value. The default value is 0. A higher value indicates a higher priority. When an event is published, the higher-priority subscription method receives the event first. Here are a few things to note:
- Only if two subscription methods use the same ThreadMode parameter do they have the same priority as the value specified by priority.
- A subscription method can only stop the continued distribution of the event if its ThreadMode parameter is POSTING.
EventBus Issues Summary (Continuously updated…)
Failure to receive sticky events in EventBus
1, cause
Since EventBus sends objects, we often build a shared object and add a tag to the shared object to make it easier to distinguish effects in reception.
For example, use the EventBusHelper utility class to send an EventBusMessage object.
2. Problems encountered
When you send A sticky event, you send it once in scenario A, then you don’t receive it yet, and then you send it again in scenario B, and then the sticky event sent by SCENARIO B can be received, and the sticky event sent by scenario A is replaced.
When we customize EventBusMessage, object.getClass() will always be the same. So much so that it replaces the previous key.
public void postSticky(Object event) {
synchronized (stickyEvents) {
stickyEvents.put(event.getClass(), event);
}
// Should be posted after it is putted, in case the subscriber wants to remove immediately
post(event);
}
Copy the code
3. Solutions
Create multiple individual objects for sending sticky services.
The above method is relatively Low, I haven’t thought of a more elegant method, if you have to share it.
Post/postSticky cannot transfer basic types.
Eg: Send a post/postSticky message directly, receive int at Subscribe, then no message is received. Change the int tag to an Integer tag.
Object is a class type (compound data type) and int is a simple data type.
EventBus.getDefault().post(111);
@Subscribe(threadMode = ThreadMode.MAIN)
public void getMessage(int tag) {
if (tag == 111)
Log.d(TAG, "received");
}
Copy the code