I have an app which load ads from two networks and sets a flash file to webview when started.This is making it too slow on startup, forums told me to use asynctask.Can some one make this code an asynctask.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
airpush=new Airpush(getApplicationContext());
airpush.startPushNotification(false);
airpush.startIconAd();
airpush.startDialogAd();
airpush.startAppWall();
mWebView = (WebView) findViewById(R.id.webview);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.getSettings().setPluginsEnabled(true);
mWebView.setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY);
mWebView.setBackgroundColor(Color.parseColor("#000000"));
mWebView.loadUrl("file:///android_asset/game.swf");
AdView adView = (AdView)this.findViewById(R.id.adView);
adView.loadAd(new AdRequest());
It will be much more helpful for you to spend a little bit of time understanding the architecture of an AsyncTask than for someone to simply make one for you.
An AsyncTask is actually a fairly simple class to extend and use. An AsyncTask can, in its simplest form, be code that runs in the background (off the UI thread -- this is what causes lockup), but is set up to allow for some code to run in the background, some code to execute before/after, and some code to execute as a progress update if necessary.
You will need to create your own class that extends AsyncTask as shown below. Your task will take three parameters. The first will get passed into the doInBackground function that runs in the background, the second is a type for a parameter that can be passed into a progress update function, and the third is a type to be passed into your onPostExecute fn that runs on the UI thread after the background function has completed. In the simple example below I will not include types to be passed to a post execute function or a progress update function, so they will be of type Void.
private class YourTask extends AsyncTask<byte[], Void, Void> {
protected Long doInBackground(byte[]... data) {
//get the array
byte[] array = data[0];
//do something with it.
HERE IS WHERE YOU RUN YOUR CODE IN THE BACKGROUND THAT IS TAKING TOO LONG ON THE UI THREAD
//return null because this type needs to match the last type for returning to the postexec fn
return null;
}
}
When you want to run your task you call the following:
new YourTask().execute(someByteArray);
So oftentimes you can stick the code that is taking a long time into that doInBackground function, but you have to be careful because it is off the UI thread and some code does have to be run on the UI thread.
I would recommend doing some profiling to see what code specifically is choking up your UI thread, and run THAT in the background using an AsyncTask. You can do that by using DDMS in Eclipse and use method profiling. Another way would be to use the Debug class and call Debug.startMethodTracing("tracefilename"); when you want to start and Debug.stopMethodTracing();. You can read more about that here. However, your code does load a url (mWebView.loadUrl) so I would assume this may be a big bottleneck!
Just as an addendum, if you want a more in depth example of an AsyncTask, here is one I C&Pd from this useful documentation:
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
// Escape early if cancel() is called
if (isCancelled()) break;
}
return totalSize;
}
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
}
The above example has code to both exemplify updating progress on the UI during the background task as well as passing a parameter that is then used by the UI thread-running post execute fn.
I can't just make your code an AsyncTask but I can give you an example and some help. This is an example of AsyncTask
public class TalkToServer extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
}
#Override
protected String doInBackground(String... params) {
//do your work here
return something;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
// do something with data here-display it or send to mainactivity
}
All of your network stuff you will put in doInBackground() then if you need to update the UI you did that in the other methods. After finishing the network stuff you can update UI in onPostExecute().
This is how you would call the task
TalkToServer myAsync = new TalkToServer() //can add params if you have a constructor
myAsync.execute() //can pass params here for `doInBackground()` method
If it is an inner class of your MainActivity then it will have access to member variables of MainActivity. If its a separate class then you can pass context to constructor like
TalkToServer myAsync = new TalkToServer(this);
and create a constructor to accept Context and any other params you want
I strongly suggest going through the docs below and make sure you understand how it works. Maybe the biggest thing to understand when getting started is that doInBackground() doesn't run on the UI so you don't want to try and update any Views here but in the other AsyncTask methods or by passing data back to the MainActivity and update there
AsyncTask
Related
I am writing a Android application which reads data from a SQLite Database and then displays the data on a next screen. Whenever I was doing a query on the database I would get an error message that too much work is being done on the main thread.
I then put my query in a new Thread:
(new Thread()
{
public void run()
{
Looper.prepare();
try
{
FPJobCardWizard data = dbHelperInstance.loadFPJobCardWizardFull(fitmentHash);
wState.fitmentItemSet(data.fitmentItemGet());
} catch (Exception e) {e.printStackTrace();}
Looper.loop();
}
}).start();
Now the gui/main thread is completing it's operation prior to the Query being complete and as a result the data variable is still empty. I read a few posts and the API documentation and it seems that I need to use a Looper (this seems to be the correct fix) but I have never used a Looper and cannot seem to get it to work.
Please can you check the code above and guide me in the right direction.
Thank you all in advance.
the best choice here will be using an AsyncTask, as it will enables you to perform all the background work in a background thread, then when the result is generated it will apply it using the UI thread:
So, as explained in the life cycle of AsyncTask, you can do all of your background work in the method doInBackground() and then do all of your UI work on the method onPostExecute() which will be executed after taking the result from doInBackground() method according to the life cycle, and to put your hands more on the AsyncTask, have a look at this example which provides the following example code:
public class AsyncTaskTestActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// This starts the AsyncTask
// Doesn't need to be in onCreate()
new MyTask().execute("my string paramater");
}
// Here is the AsyncTask class:
//
// AsyncTask<Params, Progress, Result>.
// Params – the type (Object/primitive) you pass to the AsyncTask from .execute()
// Progress – the type that gets passed to onProgressUpdate()
// Result – the type returns from doInBackground()
// Any of them can be String, Integer, Void, etc.
private class MyTask extends AsyncTask<String, Integer, String> {
// Runs in UI before background thread is called
#Override
protected void onPreExecute() {
super.onPreExecute();
// Do something like display a progress bar
}
// This is run in a background thread
#Override
protected String doInBackground(String... params) {
// get the string from params, which is an array
String myString = params[0];
// Do something that takes a long time, for example:
for (int i = 0; i <= 100; i++) {
// Do things
// Call this to update your progress
publishProgress(i);
}
return "this string is passed to onPostExecute";
}
// This is called from background thread but runs in UI
#Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
// Do things like update the progress bar
}
// This runs in UI when background thread finishes
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
// Do things like hide the progress bar or change a TextView
}
}
}
I am working on an Android project and I have a thread which is posting to a PHP API and does checks with the response.
Before the thread starts I show a progress dialog which can be cancelled. When the cancel is pressed I call thread.stop() but this shows up as deprecated.
Everything I have found on Google suggest that I have a flag and check the flag within the while loop and come out of the thread cleanly, however in my circumstances there is no loop, so how should I go about doing this?
The problem you are facing is know problem because, threads are not supposed to be stopped by calling thread.stop(); method.
Also Android discourages the use of Java Threads in Android, and Conveniently, Android has some additional support for when it comes to communicating between Threads, The Handler class provides a neat queued message mechanism, and Looper provides a handy method for processing same.
But as you mentioned you want to show a progress dialog which can be cancelled. When the cancel is pressed, so this type of functionality can be achieved using AsyncTask.
As AsyncTask is one of the easiest ways to implement parallelism in Android without having to deal with more complex methods like Threads.
Though it offers a basic level of parallelism with the UI thread, it should not be used for longer operations (of, say, not more than 2 seconds).
Mainly AsyncTask should handle your problem, Since:
It provides easy and standard recommended mechanism to publish background progress (see the Usage section here:
http://developer.android.com/reference/android/os/AsyncTask.html)
It provides method cancel(boolean); for cancelling a task(see the Cancelling a task section here:
http://developer.android.com/reference/android/os/AsyncTask.html
AsyncTask has four methods to do the task:
onPreExecute();
doInBackground();
onProgressUpdate();
onPostExecute();
And cancel(); method to handle the cancellation of the background work.
Where doInBackground() is the most important as it is where background computations are performed.
Code:
Here is a skeletal code outline with explanations:
public class AsyncTaskTestActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// This starts the AsyncTask
// Doesn't need to be in onCreate()
new DownloadFilesTask().execute(url1);
}
// Here is the AsyncTask class:
//
// AsyncTask<Params, Progress, Result>.
// Params – the type (Object/primitive) you pass to the AsyncTask from .execute()
// Progress – the type that gets passed to onProgressUpdate()
// Result – the type returns from doInBackground()
// Any of them can be String, Integer, Void, etc.
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
// Escape early if cancel() is called
if (isCancelled()) break;
}
return totalSize;
}
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
}
}
For more in depth knowledge visit following links:
https://blog.nikitaog.me/2014/10/11/android-looper-handler-handlerthread-i/
http://developer.android.com/reference/android/os/AsyncTask.html
This question already has an answer here:
Using AsyncTask
(1 answer)
Closed 8 years ago.
I want to use an AsyncTask in my app, but I am having trouble finding a code snippet with a simple explanation of how things work. I just want something to help me get back up to speed quickly without having to wade through the documentation or lots of Q&As again.
AsyncTask is one of the easiest ways to implement parallelism in Android without having to deal with more complex methods like Threads. Though it offers a basic level of parallelism with the UI thread, it should not be used for longer operations (of, say, not more than 2 seconds).
AsyncTask has four methods
onPreExecute()
doInBackground()
onProgressUpdate()
onPostExecute()
where doInBackground() is the most important as it is where background computations are performed.
Code:
Here is a skeletal code outline with explanations:
public class AsyncTaskTestActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// This starts the AsyncTask
// Doesn't need to be in onCreate()
new MyTask().execute("my string parameter");
}
// Here is the AsyncTask class:
//
// AsyncTask<Params, Progress, Result>.
// Params – the type (Object/primitive) you pass to the AsyncTask from .execute()
// Progress – the type that gets passed to onProgressUpdate()
// Result – the type returns from doInBackground()
// Any of them can be String, Integer, Void, etc.
private class MyTask extends AsyncTask<String, Integer, String> {
// Runs in UI before background thread is called
#Override
protected void onPreExecute() {
super.onPreExecute();
// Do something like display a progress bar
}
// This is run in a background thread
#Override
protected String doInBackground(String... params) {
// get the string from params, which is an array
String myString = params[0];
// Do something that takes a long time, for example:
for (int i = 0; i <= 100; i++) {
// Do things
// Call this to update your progress
publishProgress(i);
}
return "this string is passed to onPostExecute";
}
// This is called from background thread but runs in UI
#Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
// Do things like update the progress bar
}
// This runs in UI when background thread finishes
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
// Do things like hide the progress bar or change a TextView
}
}
}
Flow Diagram:
Here is a diagram to help explain where all the parameters and types are going:
Other helpful links:
What arguments are passed into AsyncTask<arg1, arg2, arg3>?
Slidenerd Android AsyncTask Tutorial: Android Tutorial For Beginners
Understanding AsyncTask – Once and Forever
Dealing with AsyncTask and Screen Orientation
How to pass multiple parameters to AsynkTask
how to pass in two different data types to AsyncTask, Android
I wanted to use AsyncTask to load images to the ListView.
private class LoadImageTask extends AsyncTask<HashMap<String,Bitmap>,Void,Bitmap>{
#SuppressWarnings("unchecked")
#Override
protected void onPostExecute(Bitmap result) {
if(model.getIconCache().get(cellIcon)!=null){
icon.setImageBitmap(model.getIconCache().get(cellIcon));
}else{
new LoadImageTask().execute(model.getIconCache());
}
}
#Override
protected Bitmap doInBackground(HashMap<String, Bitmap>... params) {
//return model.getIconCache().get(cellIcon);
return null;
}
}
Ok, I know that this not an affective code. However it works well but with a lot of memory allocation. When reading the documentation about AsyncTask it said that Asynctask can be called only from UI thread, how could it let to use inside itself? And of course I want to make my code work inside a single AsyncTask. "model" in the code is an object that is updated at runtime through another thread. So I need to find a way to use a single Asynctask with periodically control the state of an object. How do I do that? Thanks
only do in backGround runs on backGround thread and postExecute and preExecute run on UI thread itself.. For the same reason u can show and dismiss dialogs in it..
if u want to use single Asynctask for multiple purpose u can play around by passing Different constants.. in .execute() method..
I mean something like this.
Integer Constant1 = 1;
int Constant2 = 2;
and while calling,,
new Background.execute(Constan1 or 2)
and in AsyncTask
doInBackground(Object.. arg0)
{
if(arg0.equals())
{
}
else if(arg0.equals())
{
}
}
Take a look at the asynctask documentation: http://developer.android.com/reference/android/os/AsyncTask.html
private class MyTask extends AsyncTask<Void, Integer, Boolean> {
protected Boolean doInBackground(Void...) {
int i = 0;
while(true){
publishProgress(i++);
}
}
protected void onProgressUpdate(Integer... progress) {
myObject.setState(progress[0]);
}
}
You do your background stuff in the doInBackground method (which runs in the background thread).
You control the state of your object in the onProgressUpdate (which runs on the ui thread)
You send messages between the background thread and the ui thread using publishProgress. These messages could contain the state of your object.
I am using AsyncTask on button click to refresh the screen. Following is the sequence of events that happen on btn click
progress dialog shows up
The doInBackground is called and thread is initialized which calls a web service. The web service fetches/uploads data. A pass/fail flag is set once the web service is called.
My problem is the onPostExecute is never called and therefore the screen is never refreshed.
And secondly by the time the data is downloaded and the web service sets the flag my code has already hit return stmt in doInBackground.
Question is how do i stop execution in my asynctask so that the web service is done downloading/uploading the data and finally execute onPostexecute.
FYI
I also get the following warning in eclipse
The method onPostExecute(boolean) from
the type
Screen.ConnectWebService is
never used locally
private class ConnectWebService extends AsyncTask <Void, Void, Boolean>
{
private final ProgressDialog pd = new ProgressDialog(screen.this);
protected void onPreExecute() {
pd.show(Screen.this, "Sync", "Sync in progress",true,false);
}
protected Boolean doInBackground(Void... unused) {
if (SyncInProgress == false)
{
CallWSThread();//creates thread which calls web service
}
Log.d("doInBackground","doInBackground");
return SyncStatus;
}
protected Void onPostExecute(boolean result)
{
pd.dismiss();
if (result==true) drawRadioButtons();
return null;
}
}
It should be:
protected Void onPostExecute(Boolean result)
As djg noted, you have a typo in your method declaration. You can avoid these kinds of mistakes by using the annotation #Override when you're implementing methods from a super class.