4.5.2 Intent and Complex Data Transfer
Category Android Basic Tutorial
Introduction to This Section:
>
In the previous section, we learned about the basic usage of Intent, understood its seven attributes, the use of explicit and implicit Intents, how to customize implicit Intents, and finally provided some commonly used system Intents! This section will discuss how to transfer data using Intent. Let's get started with this section's content.
1. Transferring Simple Data with Intent
>
Do you remember how we learned to transfer simple data between two Activities?
You can directly store data by calling the putExtra() method of Intent, and then retrieve the data by calling getXxxExtra after obtaining the Intent. For multiple data items, you can use a Bundle object as a container. Store the data in the Bundle by calling putXxx, then store the Bundle in the Intent by calling putExtras(). After obtaining the Intent, call getExtras() to retrieve the Bundle container, and then call getXXX to retrieve the corresponding data. The data storage is somewhat similar to a Map's <key, value> structure.
2. Transferring Arrays with Intent
>
Handling arrays is straightforward:
Writing Arrays:
bd.putStringArray("StringArray", new String[]{"呵呵","哈哈"});
// You can replace StringArray with other data types like int, float, etc.
Reading Arrays:
String[] str = bd.getStringArray("StringArray");
3. Transferring Collections with Intent
>
Transferring collections is a bit more complex and depends on the type:
1) List<Basic Data Type or String>
Writing Collections:
intent.putStringArrayListExtra(name, value);
intent.putIntegerArrayListExtra(name, value);
Reading Collections:
intent.getStringArrayListExtra(name);
intent.getIntegerArrayListExtra(name);
2) List<Object>
Cast the list to Serializable type and then pass it (using Bundle as a medium):
Writing Collections:
putExtras(key, (Serializable)list);
Reading Collections:
(List<Object>) getIntent().getSerializable(key);
Note: The Object class needs to implement the Serializable interface.
3) Map<String, Object>, or more complex structures
The solution is to wrap it in a List:
// Transferring 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();
// Define a list to pass the ArrayList<Object> in the bundle, which is necessary
ArrayList bundlelist = new ArrayList();
bundlelist.add(list);
bundle.putParcelableArrayList("list", bundlelist);
intent.putExtras(bundle);
startActivity(intent);
4. Transferring Objects with Intent
There are two ways to transfer objects: converting the object to a JSON string or using serialization with Serializable or Parcelable. It is not recommended to use Android's built-in JSON parser; instead, use third-party libraries like fastjson or Gson.
1) Converting Objects to JSON Strings
Example using Gson:
Model:
public class Book {
private int id;
private String title;
//...
}
public class Author {
private int id;
private String name;
//...
}
Writing Data:
Book book = new Book();
book.setTitle("Java Programming Thoughts");
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);
Reading 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) Using Serializable or Parcelable for Object Serialization
1. Serializable Implementation:
>
The business bean implements the Serializable interface and includes getter and setter methods.
2. Parcelable Implementation:
General Process:
>
The business bean inherits the Parcelable interface and overrides the writeToParcel method to serialize the object into a Parcel object.
Explanation:
>
By writing the object to a Parcel with writeToParcel, and then recreating the object from the Parcel with createFromParcel, you map the object to a Parcel and back. Think of the Parcel as a stream; write the object to the stream with writeToParcel, and read it back with createFromParcel. The process must be consistent in order and implemented by you.
Example Code for Implementing 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 Plugin for Generating Parcelable Code:
Use the Intellij/Android Studio plugin android-parcelable-intellij-plugin. Simply press ALT+Insert to generate the Parcelable interface code automatically.
Additionally, Android extensively uses Parcelable objects, and implementing the Parcelable interface can be tedious. You can use third-party frameworks like Parceler, although Maven issues may prevent immediate use.
Reference: Android Parcelable Auto-Generation
Comparison of the Two Serialization Methods:
- 1) Parcelable is more efficient in terms of memory usage compared to Serializable, so it is recommended.
- 2) Serializable creates a large number of temporary variables during serialization, leading to frequent garbage collection.
- 3) Parcelable is not suitable for storing data on disk because it does not guarantee data persistence in the event of external changes. Despite its lower efficiency, Serializable is recommended for such cases.
5. Transferring Bitmap with Intent
Since Bitmap implements the Parcelable interface by default, it can be directly transferred.
Example Code:
Bitmap bitmap = null;
Intent intent = new Intent();
Bundle bundle = new Bundle();
bundle.putParcelable("bitmap", bitmap);
intent.putExtra("bundle", bundle);
6. Using Global Data for Convenience
>
If you need to pass simple data through multiple activities (e.g., Activity1 -> Activity2 -> Activity3 -> Activity4), and you want to pass some data to Activity4, it would be impractical to pass it through each activity.
Instead, you can consider using the Application global object to store data that needs to be accessible from anywhere.
The Application object is created by the Android system when the program starts and is the only one created, making it a singleton. The Application object has the longest lifecycle in the program, equal to the program's lifecycle. If you need to store values that are static (or can change), and you want to access them globally, you can use the Application object. To use a custom Application class, you need to extend the Application class and inform the system to instantiate our custom Application instead of the default one. This is done by adding the name attribute to our application tag in the AndroidManifest.xml.
Key Code Sections:
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) Calling in Required Places:
class Blah extends Activity {
@Override
public void onCreate(Bundle b){
...
MyApp appState = ((MyApp)getApplicationContext());
String state = appState.getState();
...
}
}
Advanced Approach:
The Application component has its own lifecycle, and we can obtain the Application object in the onCreate method. Here's 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(){
super.onCreate();
instance = this;
}
}
You can then call MyApp.getInstance()
from anywhere to get the global Application object.
Important Notes:
The Application object resides in memory and can be killed by the system to reclaim memory. For example, if you store a user account in the Application object in Activity1 and retrieve it in Activity2, the app might crash if the system kills the app and a new Application object is created when the app is reopened. This can lead to a NullPointerException. It's crucial to localize important data and perform null checks when accessing variables. This issue also applies to singleton objects and public static variables.
7. Singleton Pattern for Parameter Passing
The Application example above is based on the singleton pattern, which ensures that only one instance of a class exists in the system. This allows for efficient parameter setting in one place and accessing them elsewhere.
Example Code:
① Define a Singleton Class:
public class XclSingleton
{
private static XclSingleton instance = null;
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");
Summary:
This section covered complex data transmission using Intent, as well as parameter passing using Application and the singleton pattern. These methods should simplify data transmission and are highly efficient. Thank you for reading.
Tutorial Links:
-1.0 Android Basic Beginner Tutorial
-1.0.1 2015 Latest Android Basic Beginner Tutorial Contents
-1.1 Background and System Architecture Analysis
-1.2 Development Environment Setup
-1.2.1 Using Eclipse + ADT + SDK to Develop Android APP
-1.2.2 Using Android Studio to Develop Android APP
-1.3 Solving SDK Update Issues
-1.4 Genymotion Emulator Installation
-1.5.1 Git Tutorial for Basic Local Repository Operations
-1.5.2 Git: Setting Up a Remote Repository on GitHub
-1.6 How to Use 9-Patch Images
-1.7 Interface Prototype Design
-1.8 Project Source Analysis (Various Files, Resource Access)
-1.9 Android App Signing and Packaging
-1.11 Decompiling APK to Retrieve Code & Resources
-2.1 Concepts of View and ViewGroup
-2.2.1 LinearLayout (Linear Layout)
-2.2.2 RelativeLayout (Relative Layout)
-2.2.3 TableLayout (Table Layout)
-2.2.4 FrameLayout (Frame Layout)
-2.2.5 GridLayout (Grid Layout)
-2.2.6 AbsoluteLayout (Absolute Layout)
-2.3.1 Detailed Explanation of TextView (Text Box)
-2.3.2 Detailed Explanation of EditText (Input Box)
-2.3.3 Button and ImageButton (Image Button)
-2.3.5.RadioButton (Radio Button) & Checkbox (Checkbox)
-2.3.6 ToggleButton and Switch (Toggle Switch)
-2.3.7 ProgressBar (Progress Bar)
-2.3.9 RatingBar (Star Rating Bar)
-2.4.1 ScrollView (Scroll Bar)
-2.4.2 Date & Time Components (Part 1)
-2.4.3 Date & Time Components (Part 2)
-2.4.5 Simple Usage of ListView
- 2.4.6 BaseAdapter Optimization
- 2.4.7 ListView Focus Issues
- 2.4.8 ListView Checkbox Misalignment Solution
- 2.4.9 ListView Data Update Issues
- 2.5.0 Building a Reusable Custom BaseAdapter
- 2.5.1 Implementing Multiple Item Layouts in ListView
- 2.5.2 Basic Usage of GridView (Grid View)
- 2.5.3 Basic Usage of Spinner (Dropdown List)
- 2.5.4 Basic Usage of AutoCompleteTextView (Auto-complete Text Field)
- 2.5.5 Basic Usage of ExpandableListView (Collapsible List)
- 2.5.6 Basic Usage of ViewFlipper (Flip View)
- 2.5.7 Basic Usage of Toast
- 2.5.8 Detailed Explanation of Notification (Status Bar Notification)
- 2.5.9 Detailed Explanation of AlertDialog (Dialog Box)
- 2.6.0 Basic Usage of Other Common Dialogs
- 2.6.1 Basic Usage of PopupWindow (Floating Box)
- 2.6.2 Menu (Menu)
- 2.6.3 Simple Usage of ViewPager
- 2.6.4 Simple Usage of DrawerLayout (Official Side Slider Menu)
- 3.1.1 Event Handling Mechanism Based on Listeners
- 3.2 Event Handling Mechanism Based on Callbacks
- 3.3 Analysis of Handler Message Passing Mechanism
- 3.4 TouchListener vs OnTouchEvent + Multi-touch
- 3.5 Listening to Changes in EditText Content
- 3.6 Responding to System Setting Events (Configuration Class)
- 3.7 AsyncTask Asynchronous Task
- 3.8 Gestures (Gestures)
- 4.1.1 Activity Beginner's Guide
- 4.1.2 Activity Intermediate Guide
- 4.1.3 Activity Advanced Guide
- 4.2.1 Service Introduction
- 4.2.2 Service Advanced
- 4.2.3 Service Mastery
- 4.3.1 BroadcastReceiver Beginner's Guide
- 4.3.2 BroadcastReceiver In-depth Guide
- 4.4.1 ContentProvider Introduction
- 4.4.2 ContentProvider Deep Dive – Document Provider
- 4.5.1 Basic Usage of Intent
- 4.5.2 Passing Complex Data with Intent
- 5.1 Basic Overview of Fragment
- 5.2.1 Fragment Example Detailed – Bottom Navigation Bar Implementation (Method 1)
- 5.2.2 Fragment Example Detailed – Bottom Navigation Bar Implementation (Method 2)
- 5.2.3 Fragment Example Detailed – Bottom Navigation Bar Implementation (Method 3)
- 5.2.4 Fragment Example Detailed – Bottom Navigation Bar + ViewPager Page Sliding
- 5.2.5 Fragment Example Detailed – Simple Implementation of News (Shopping) App List Fragment
- 6.1 Data Storage and Access – File Storage and Reading
- 6.2 Data Storage and Access – SharedPreferences for Saving User Preferences
- 6.3.1 Data Storage and Access – Introduction to SQLite Database
- 6.3.2 Data Storage and Access – Further Exploration of SQLite Database
- 7.1.1 Android Network Programming Essentials and HTTP Protocol Study
- 7.1.2 Study of Android HTTP Request and Response Headers
- 7.1.3 Android HTTP Request Method: HttpURLConnection
- 7.1.4 Android HTTP Request Method: HttpClient
- 7.2.1 Android XML Data Parsing
- 7.2.2 Android JSON Data Parsing
- 7.3.1 Android File Upload
- 7.3.2 Android File Download (1)
- 7.3.3 Android File Download (2)
- 7.4 Android Calling WebService
- 7.5.1 Basic Usage of WebView (Web View)
- 7.5.2 Basic Interaction Between WebView and JavaScript
- 7.5.3 Considerations for WebView in Android 4.4 and Later
- 7.5.4 WebView File Download
- 7.5.5 WebView Cache Issues
- 7.5.6 WebView Handling Error Codes from Web Pages
- 7.6.1 Network Basics Preparation for Socket Study
- 7.6.2 TCP Protocol Based Socket Communication (1)
- 7.6.3 TCP Protocol Based Socket Communication (2)
- 7.6.4 UDP Protocol Based Socket Communication
- 8.1.1 Summary of 13 Drawable Types in Android Part 1
- 8.1.2 Summary of 13 Drawable Types in Android Part 2
- 8.1.3 Summary of 13 Drawable Types in Android Part 3
- 8.2.1 Comprehensive Analysis of Bitmap (Bitmap) Part 1
- 8.2.2 OOM Issues Caused by Bitmap
- 8.3.1 Detailed Explanation of Three Drawing Tool Classes
- 8.3.2 Practical Examples of Drawing Classes
- 8.3.3 Paint API – MaskFilter (Mask)
- 8.3.4 Paint API – Xfermode and PorterDuff Detailed Explanation (Part 1)
- 8.3.5 Paint API - Xfermode and PorterDuff Explained (Part 2)
- 8.3.6 Paint API - Xfermode and PorterDuff Explained (Part 3)
- 8.3.7 Paint API - Xfermode and PorterDuff Explained (Part 4)
- 8.3.8 Paint API - Xfermode and PorterDuff Explained (Part 5)
- 8.3.9 Paint API - ColorFilter (Color Filter) (1/3)
- 8.3.10 Paint API - ColorFilter (Color Filter) (2/3)
- 8.3.11 Paint API - ColorFilter (Color Filter) (3/3)
- 8.3.12 Paint API - PathEffect (Path Effect)
- 8.3.13 Paint API - Shader (Image Rendering)
- 8.3.14 Paint API - Enumerations/Constants and ShadowLayer Shadow Effect
- 8.3.15 Paint API - Typeface (Font Style)
- 8.3.16 Canvas API Explained (Part 1)
- 8.3.17 Canvas API Explained (Part 2) - Clipping Methods
- 8.3.18 Canvas API Explained (Part 3) - Matrix and drawBitmapMesh
- 8.4.1 Android Animation Collection - Frame Animation
- 8.4.2 Android Animation Collection - Tween Animation
- 8.4.3 Android Animation Collection - Property Animation - Introduction
- 8.4.4 Android Animation Collection - Property Animation - Further Exploration
- 9.1 Using SoundPool to Play Sound Effects (Duang~)
- 9.2 MediaPlayer to Play Audio and Video
- 9.3 Using Camera to Take Photos
- 9.4 Using MediaRecord to Record Audio
- 10.1 TelephonyManager (Phone Manager)
- 10.2 SmsManager (SMS Manager)
- 10.3 AudioManager (Audio Manager)
- 10.4 Vibrator (Vibrator)
- 10.5 AlarmManager (Alarm Service)
- 10.6 PowerManager (Power Service)
- 10.7 WindowManager (Window Management Service)
- 10.8 LayoutInflater (Layout Service)
- 10.9 WallpaperManager (Wallpaper Manager)
- 10.10 Sensor Topics (1) - Introduction
- 10.11 Sensor Topics (2) - Orientation Sensor
- 10.12 Sensor Topics (3) - Accelerometer/Gyroscope Sensor
- 10.12 Sensor Topics (4) - Understanding Other Sensors
- 10.14 Android GPS Introduction
- 11.0 "2015 Latest Android Basic Tutorial" - Completion Celebration
- 12.1 Android Practice: DrySister App (First Edition) - Project Setup and Basic Implementation
- 12.2 DrySister App (First Edition) - 2. Parsing Backend Data
- 12.3 DrySister App (First Edition) - 3. Image Loading Optimization (Building a Simple Image Cache Framework)
- 12.4 DrySister App (First Edition) - 4. Adding Data Caching (Introducing SQLite)
- 12.5 DrySister App (First Edition) - 5. Code Review, Adjustments, and Logging Class Writing
- 12.6 DrySister App (First Edition) - 6. Icon Creation, Obfuscation, Signing, APK Slimming, and App Release