Design Patterns-Singleton mode (Singleton) thinking and encountering pits in Android development application scenarios

Source: Internet
Author: User
Tags eventbus

Introduced

In the previous blog, we explained in detail the writing and the problem of various singleton. This article mainly introduces the various application scenarios in Android development and the comparison of static class methods, and illustrates the actual examples.

The thinking of single case

Having written so many single cases, we quickly forget why we need a single case and review the nature of the singleton.

The nature of a singleton: the number of control instances

Globally, there is only one object and can be accessed globally.

Number of control instances

Sometimes thinking if we need to control the number of instances is not only one, but 2, 3, 4 or any number? How we control the number of instances, in fact, the realization of the idea is simple, is through the map cache instance, control the number of caches, when there is a call to return an instance, which involves scheduling problems. Thinking about this in real-world Android development? Indeed, if you have read my previous analysis of the single case of the blog mentions that Guo God and Hong Yang great god have lrucache to achieve the picture cache, is not the control of the number of instances of the application scenario. LRUCache internal with Linkedhashmap holding object. With LRUCache cache images to memory, the number of images is the number of instances we need to control, generally based on the size of memory to open space, image, according to the image address URL to take in memory images do not have access to the network, the internal use of the least recently used scheduling algorithm to control the image storage.
Concrete implementation look more complicated, the details to see two great gods of the CDNs blog bar.

Application Scenarios for single cases

Back in the development scene, think about why we need a singleton. If you need to provide a global access point to getInstance() do something about it. Do we have any other options besides the single case?
Go back to look at the Android source code, there is such a class. The Java.lang.Math class provides operations and method calculations for numbers, and its implementation is all methods to static修饰符 provide class-level access with wrappers. Because when we call the math class, as long as one of its class methods does data manipulation, it doesn't care about object state.

The singleton does not need to maintain any state, only provides the method of global access, this case considers using static class, static method is faster than Singleton, because static binding is done at compile time.
If you need to put some tool methods together, you can choose to use static methods, but other things that require singleton access to resources and focus on object state should use singleton mode.

Android development in single-case applications

The picture loading framework is a good example of the actual usage scenario in Android development for a single case. When I first approached Android, I used Android Universal Image Loader a singleton, because it needed to cache pictures, do various operations on the cached collection of pictures, focus on the state of the objects in the singleton, and obviously need access to resources. This fits into the characteristics of a single case. Also in the popular Eventbus is a singleton, because it caches the various components sent over the event object, and is responsible for distributing, the individual components need to register themselves with the same Eventbus object to receive event events, it must be a globally unique object, So we used a single case.
The single case of Eventbus is double check and lock single case

staticvolatile EventBus defaultInstance;publicstaticgetDefault() {        ifnull) {            synchronized (EventBus.class) {                ifnull) {                    new EventBus();                }            }        }        return defaultInstance;    }

Finally found in the Android source code, a very important class Layoutinflater itself is also using a singleton mode.

Retrofit Network Framework static Class tool class application

In one of my projects using retrofit to do network access, this requires a specific retrofit object operation network. And it's best to provide a way to get this globally unique retrofit object. At first I was also struggling with a singleton or a static class. Because the analysis of retrofit on the domestic website is not much used, and the analysis of this single case and static class on the network is too much and chaotic.
Finally, until I see this blog, feeling is still a foreigner, finally my project uses the following code to instantiate the retrofit object. This is the exact code. At present, there is no problem, we use retrofit as an example of the reference bar. (Code is based on the latest Retrofit-2.0 version)

 Public classServicegenerator { Public StaticFinal String Api_base_url ="Http://your.api-base.url";Private StaticOkhttpclient.builder httpClient =NewOkhttpclient.builder ();Private StaticRetrofit.builder Builder =NewRetrofit.builder (). BASEURL (Api_base_url). Addconverterfactory (gsonconverterfactory. Create ()); Public Static<S> SCreateService(class<s> ServiceClass) {Retrofit Retrofit = builder.client (Httpclient.build ()). build ();returnRetrofit.create (ServiceClass); }}

So write, use static class instead of Singleton, because the network access as a tool class, only need to get the retrofit instance object to do network operation, Servicegenerator tool class inside do not maintain internal variables and do not care about the state change of internal variables.

Single-case developed pits

Stepping on a pit is a process that every developer has to go through, and here are some of the pits I've encountered after using a single case. It is believed that every beginner Android developer encounters this problem. Pass data between two activity components, intent and bundles can only pass simple basic type data and String objects
(It is also possible to pass objects, which requires parcelable and serializable interfaces).
When it is necessary to pass only a few value problems, but if you need to pass more data to feel the code is not concise and the key value is much easier to receive errors, passing objects need to inherit the Parcelable interface to write a large number of duplicate template code. Is there an elegant solution?

Passing the pit of an object with a singleton object application

I believe some people have read the same blog like I did, "gracefully passing objects with application." At that time I saw such a blog, the real feeling of life, like a savior, feel the problem of transferring objects between components.

Elder language: Too young too simple sometimes naive

Let's talk about what happens if you really use application to pass objects. The original blog is such that application is provided by the system is a globally unique object, and any component can access it. In the subclass of the custom inheritance application, save the internal variable, take the internal variable and set the value by the activity sent, After StartActivity also accesses the Application object in the received activity to retrieve the internal variable to get the object to be passed. There is no complex intent to pass the value.
But if you do: The program will definitely collapse or not get the data.

The actual operating situation is this:
1. If you are in the activity of receiving data, press the Home button to return to your desktop and not return your app for a long time.
2. The system may kill the process when the system is running out of memory.
3. When you enter your app from the recent program run list, the system will default to the state you just left and go directly to the activity that receives the data.
4. Then call the various life cycle method callbacks, where the program will eject the null pointer nullpointerexception the exception causing the crash whenever it runs to fetch data rows from application.
5. Believe me it must be, if it doesn't crash it's just because you have the default initialization method in the internal variable. This is certainly not the data you want.

Because the entire process takes a long time, we can use the ADB command to kill the process adb shell kill , simulating an operation that has been killed by the system for a long time without returning to the application. If you feel trouble, you can also turn on device monitor-to select your app-use the red button to Stop process to kill processes.

The main cause of the program crash is:

The system will revert to the previously left state, go directly to an activity component instead of opening the activity in turn, so that the activity of your sending data does not run and will not pass the value to the application, and naturally will not get the value.

So do not believe that the "graceful use of application transfer objects" This blog, this is a pit!
Note that the original text is dont-store-data-in-the-application-object Chinese translation of the blog in this, you can click on the view will be detailed.

Eventbus's pit.

At that time is also writing a project, feel intent pass data too troublesome, according to Appliaction can pass the idea of data, in fact, you can also write a singleton to save global data, each component out of the implementation of components to transfer data between. Then very network search, found that Eventbus also realized the same idea, Eventbus itself is the use of a singleton mode. The foreshadowing of the previous blog is here.

Eventbus:android Event Publish/Subscribe framework simplifies Android event delivery by decoupling publishers and Subscribers

The event is sent by one component, and the other component registers with the Eventbus and then responds to the data by the method. It's a hole in there, too.
Of course I did not say Eventbus has a problem, but improper use will cause the crash program to crash.
The project was the code written in accordance with the standard Eventbus process, no problem. Or the above situation, press the home button for a long time did not return to the application, again into the program crash.
The reason is still the same:

The system recovers from the scene, directly running the activity that receives the data, and not running to the activity component that sends the data, cannot fetch the data, because there is no data sending at all.

Incidentally,

Using the Kill app, this method can check out many unexpected problems in the app.

Solutions

The problem with single-instance data transmission is that memory is easily recycled by virtual machines. What we need to solve is how to save data and persist data.
In fact, there is no good solution.

    • or pass data directly to the Activity via intent.
    • Persist data to disk using several official recommended methods, and then fetch data.
    • The value of the variable is always checked for non-null when using the data, so the data is not
    • Using Eventbus to pass data, use the Onsaveinstancestate (bundle Outstate) method to save the data and wait for the recovery value using OnCreate (Bundle savedinstancestate).
Package Activity Jump Method

For the first item, I provide a simple wrapper jump method that simplifies the code logic for Inten passing data

 Public  class myactivity extends appcompatactivity{    key value of//intent    protected Static FinalString Type_key ="Type_key";protected Static FinalString Type_title ="Type_title";//Received Data     PublicString Mkey; PublicString Mtitle;//Package Jump method Public Static void Launch(activity activity, string key, string title) {Intent Intent =NewIntent (activity, boarddetailactivity.class);        Intent.putextra (Type_title, TITLE);        Intent.putextra (Type_key, KEY);    Activity.startactivity (Intent); }@Override    protected void onCreate(Bundle savedinstancestate) {//Get DataMkey = Getintent (). Getstringextra (Type_key); Mtitle = Getintent (). Getstringextra (Type_title);} }

Using code, just one line

 MyActivity.launch(this, key, title);

The whole logic is to implement the class method in the jump component, the key value of the passed value is written in the form of the member class variable in the activity, the data needs to be passed into intent, simplifying the caller's usage code.

Onsaveinstancestate Saving Data

The time to invoke the Onsaveinstancestate () method is:

As long as an activity is done in the stack and not at the top of the stack (initiating a jump to other activity or clicking the Home button), this activity needs to call Onsaveinstancestate,
If the activity is a stack action (click Back or Execute Finish), the onsaveinstancestate will not be called.

This is exactly what we have done in our program crash, which is the key point of the problem.
All we need to do is save the data in the Onsaveinstancestate callback method and wait for the data to recover.
The code has nothing to do with outState.putParcelable(KEY, mData); it, and then takes the data from the savedinstancestate in the OnCreate.
Hint that the data being put needs to implement the Parcelable interface, if you do not want to write a lot of template code can use the Android parcelable code generator plug-in quickly into the codes.

Summarize
    • Finally finished, a single-case model to write two blog, the previous blog is mainly to illustrate a variety of single-instance writing and analysis.
    • This article mainly introduces the comparison of the new enumeration single example
    • There are also singleton scenarios and considerations, as well as a single case scenario in Android development. The singleton mode actually has the application in the source code and many open source frameworks, writes the singleton Analysis single case and the static class method and the suitable scene to write the good code.
    • Finally, I summarize the pits and solutions I encountered when I used the singleton.

Design Patterns-Singleton mode (Singleton) thinking and encountering pits in Android development application scenarios

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.