Turn: Android asynchronous Task design (Asynctask)

Source: Internet
Author: User

The idea here is that I've extracted the code logic from the view of the Android source code, so I'm not going to be 100% compliant with the original design ideas of Google engineers (or maybe 0%), but this article will certainly help you understand asynctask, and there may be some things you haven't found before.

As we all know, the main thread of Android (also called UI thread, thread ID 1) has some restrictive policies, making the main thread some things can not be done, such as access to the network is not allowed, otherwise is reported, But after 2.3, you can change its throttling policy by adding the following code, forcing the main thread to have access to the network:

Copy CodeThe code is as follows:
if (Android.os.Build.VERSION.SDK_INT > 9) {
Strictmode.threadpolicy policy = new StrictMode.ThreadPolicy.Builder (). Permitall (). build ();
Strictmode.setthreadpolicy (Policy);
}

But Strictmode is a development tool mainly used to detect disk and network access in the main thread, rather than let you do this "bad" thing, in fact, Android such restrictions are good, forcing developers to value the user experience, a negative example is Windows, the main thread can do anything, Some lazy developers put all the tasks into the main thread, so that threads often good cards, such as the editor UE or notepad++ open a network (such as Samba server) files, if suddenly the network is interrupted, then your entire editor is stuck, it will wait a long time to react, But I'm not sure if that's because the mainline thread has access to the network, but Windows often cards for this reason. Another positive example is iOS, which is extremely responsive, so when there is a user input event, the kernel has a corresponding dispatch, giving priority to responding to user actions.

Or back to the point, because the main thread of these restrictions so that developers have to write multiple threads, of course, you can not asynctask, but you do not have to avoid multi-threading, if you do not, it is possible to use handler and thread, I think a lot of people when beginners are so dry, including me, because at that time there is probably not found this class, so often write handler and thread, write write to find some code is the same, you write the handler and thread anonymous class is definitely duplicate code, as follows:

Copy CodeThe code is as follows:
[Final Handler Handler = new Handler () {
public void Handlemessage (Message msg) {
System.out.println ("The Hard has done!");
... front end code
}
};
New Thread () {
public void Run () {
Dohardwork ();
Handler.sendemptymessage (0);
}

private void Dohardwork () {
... back end code
}
}.start ();

You may want to reuse the code, of course, you can use the copy of the code, you use it as long as the ellipsis to write your code on it, but the better reuse is to wrap it in a class, OK, then we simply encapsulate it, then, it becomes this:

Copy CodeThe code is as follows:
public class Handlerandthread {
Private Handler Handler = new Handler () {
public void Handlemessage (Message msg) {
System.out.println ("The Hard has done!");
//...
}
};

public void Doinbackground () {
New Thread () {
public void Run () {
Dohardwork ();
Handler.sendemptymessage (0);
}


private void Dohardwork () {
// ...
}
};
}
}

This seems to not work, because can not tell the background thread to do what, do not know the notification, to reuse or copy code, we can add two methods, one in the foreground call a call in the background, as long as the definition of a new class can be reused, so the code becomes this:

Copy CodeThe code is as follows:
public class Handlerandthread {
Private Handler Handler = new Handler () {
public void Handlemessage (Message msg) {
System.out.println ("The Hard has done!");
Runinfrontend (); Added
}
};

public void Doinbackground () {
New Thread () {
public void Run () {
Dohardwork ();
Handler.sendemptymessage (0);
}

private void Dohardwork () {
Runinbackend (); Added
}
};
}

Added
protected void Runinbackend () {
}

Added
protected void Runinfrontend () {
}
}

A reusable class comes out, we write a subclass and invoke it with an activity:

Copy CodeThe code is as follows:
public class Mainactivity extends Activity {
@Override
protected void OnCreate (Bundle savedinstancestate) {
Super.oncreate (savedinstancestate);

New Subhandlerandthread (). Doinbackground ();
}

Class Subhandlerandthread extends Handlerandthread {
protected void Runinbackend () {
try {
Thread.Sleep (10 * 1000);
} catch (Interruptedexception e) {
E.printstacktrace ();
}
}

protected void Runinfrontend () {
System.out.println ("Task had been done");
}
}
}

This is not more than the direct write thread and handler concise a lot of it, here I use sleep to mold like a long time transaction, if in the real environment, we may be to download, if it is downloaded, we may want to pass in the parameters to the background thread, to let him download as we need, We add a parameter to the Doinbackground method, so the code for the Handlerandthread class becomes this:

Copy CodeThe code is as follows:
public class Handlerandthread {
...

public void Doinbackground (final String URL) {//Added URL
New Thread () {
public void Run () {
Dohardwork ();
Handler.sendemptymessage (0);
}

private void Dohardwork () {
Runinbackend (URL); Added URL
}
};
}

protected void runinbackend (String URL) {//Added URL
}

...
}

And the code for the calling class becomes this:

Copy CodeThe code is as follows:
public class Mainactivity extends Activity {
@Override
protected void OnCreate (Bundle savedinstancestate) {
Super.oncreate (savedinstancestate);

String url = "Http://path/to/file";
New Subhandlerandthread (). Doinbackground (URL); Added URL
}

Class Subhandlerandthread extends Handlerandthread {
@Override
protected void runinbackend (String URL) {//Added URL
System.out.println ("Start download from URL:" + URL);
try {
Thread.Sleep (10 * 1000);
} catch (Interruptedexception e) {
E.printstacktrace ();
}
}

@Override
protected void Runinfrontend () {
System.out.println ("Finish Download");
}
}
}

If it is the next file, do we add a progress update method, and then become this:

Copy CodeThe code is as follows:
public class Handlerandthread {
Private Handler Handler = new Handler () {
public void Handlemessage (Message msg) {
Switch (msg.what) {//Added
Case 0:
Runinfrontend ();
Break

Case 1:
Runinfrontendprogress (MSG.ARG1);
Break
}
}
};

...

Final protected void publishprogress (int progress) {//Added
Handler.obtainmessage (1, progress, 0);
}

protected void runinfrontendprogress (int progress) {//Added
}
}

public class Mainactivity extends Activity {
...

Class Subhandlerandthread extends Handlerandthread {
@Override
protected void runinbackend (String URL) {
System.out.println ("Start download from URL:" + URL);
for (int i = 0; i < ++i) {
try {
Thread.Sleep (1000);
} catch (Interruptedexception e) {
E.printstacktrack ();
}
Publishprogress (I*10); Added
}
}

...

@Override
protected void runinfrontendprogress (int progress) {//Added
System.out.println ("Progress:" + Progress);
}
}
}

You may not have the patience of a version of the evolution of one version, then I will jump, a few more needs: first, we downloaded the path may be to get the file, so we give the Runinfrontend method to add an input parameter filepath representation path; The method that must be implemented by the handle class is changed into an abstract method, and the class is also changed into an abstract method; I change some of the method names in the code to make them better understood, change the doinbackground to execute, change the runinfrontend to OnPostExecute, Change the runinfrontendprogress to Onprogressupdate. The final version is as follows:

Copy CodeThe code is as follows:
Public abstract class Handlerandthread {
Private Handler Handler = new Handler () {
public void Handlemessage (Message msg) {
Switch (msg.what) {
Case 0:
OnPostExecute ((String) msg.obj);
Break


Case 1:
Onprogressupdate (MSG.ARG1);
Break
}
}
};

public void Doinbackground (final String URL) {
New Thread () {
public void Run () {
String result = runinbackend (URL);
Handler.obtainmessage (0, result);
}


};
}

Final protected void publishprogress (int progress) {
Handler.obtainmessage (1, progress, 0);
}


Abstract protected string runinbackend (string url);
protected void OnPostExecute (String filePath) {}
protected void Onprogressupdate (int progress) {}
}
public class Mainactivity extends Activity {
@Override
protected void OnCreate (Bundle savedinstancestate) {
Super.oncreate (savedinstancestate);


String url = "Http://path/to/file";
New Subhandlerandthread (). Doinbackground (URL);
}

Class Subhandlerandthread extends Handlerandthread {
@Override
Protected string runinbackend (string url) {
System.out.println ("Start download from URL:" + URL);
for (int i = 0; i < ++i) {
try {
Thread.Sleep (1000);
} catch (Interruptedexception e) {
E.printstacktrace ();
}
Publishprogress (I*10);
}

return "/path/to/file";
}

@Override
protected void OnPostExecute (String filePath) {
System.out.println ("Download finished");
}

@Override
protected void Onprogressupdate (int progress) {
System.out.println ("Progress:" + Progress);
}
}
}

This is not like the Android Asynctask, I think Google is due to this kind of need to make this category, the Android official website is described Asynctask:

This class allows to perform background operations and publish results on the UI thread without have to manipulate threa DS and/or handlers.

This class makes it possible to perform operations in the background and then publish the results to the UI thread without using thread and handler. In fact, his internal implementation is to encapsulate the thread and handler, so you do not have to use these two lower classes directly, but his purpose is code reuse, and his implementation is similar to the class we wrote above. There are several differences: first, Asynctask uses a thread pool instead of a single thread to perform background tasks, and the thread pool is common to the entire process because his thread pool object is a static member variable, a lot of people are mistaken and mistakenly think that the more threads asynctask Create, This is not absolutely correct, because the thread pool is dynamically adjusted according to the load, and has the maximum and idle timeout, the configuration of Asynctask is minimum 5, maximum 128, idle timeout of 1 seconds, of course you can also configure the number of threads according to the number of tasks thread increment, about the thread pool, can refer to here, Later I will write an article on the blog to discuss the Java thread pool; the input and output parameters of asynctask are used generics; Asynctask support interrupts the current task.

Now know asynctask design ideas, is not very simple, so it is recommended that children shoes to look at its source, anyway, I write code when the habit of viewing the source, because I will be curious about how it is implemented, see the source has many advantages, such as can learn good API design ideas, software architecture.

Turn: Android asynchronous Task design (Asynctask)

Related Article

E-Commerce Solutions

Leverage the same tools powering the Alibaba Ecosystem

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

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.