I have 2 methods in onCreate which I need to run one after the other ie...the second method will start once the first method is complete irrespective of how much time it takes.Please help me.
new Handler().postDelayed(new Runnable() {
/*
* Showing splash screen with a timer. This will be useful when you
* want to show case your app logo / company
*/
#Override
public void run() {
// This method will be executed once the timer is over
// Start your app main activity
populateList();
// close this activity
//finish();
}
}, 20000);getContactList();
populateList() method
** public void populateList() {
Log.i("Populate List","Entered");
Toast.makeText(this,String.valueOf(Common.selectedContactNos.size()),Toast.LENGTH_LONG).show();
displayRecyclerAdapter = new DisplayRecyclerAdapter(DisplayContacts.this);
LinearLayoutManager mLinearLayoutManager = new LinearLayoutManager(this);
recyclerView_contacts.setAdapter(displayRecyclerAdapter);
recyclerView_contacts.setLayoutManager(mLinearLayoutManager);
displayRecyclerAdapter.notifyDataSetChanged();
}**
just use AsyncTask
call TaskOne class like-
new TaskOne().execute();
private class TaskOne extends AsyncTask<Void,Void,Void>
{
#Override
protected Void doInBackground(Void... params) {
getContactList();
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
populateList();
}
}
Call both method inside run method with the sequence you want. Replace your code with below code
new Handler().postDelayed(new Runnable() {
/*
* Showing splash screen with a timer. This will be useful when you
* want to show case your app logo / company
*/
#Override
public void run() {
// This method will be executed once the timer is over
// Start your app main activity
populateList();
getContactList();
// close this activity
//finish();
}
}, 20000);
I made very simple app. Basically I have activity A that starts activity B if button is pressed. So here's the code
openMapFAB.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(getActivity(), MapActivity.class);
intent.putExtra("routeId", id);
startActivity(intent);
}
});
But here's the problem. activity B is very heavy (it basically open map (mapsforge) and do other heavy calculations). So when pressing buton my UI freezes about 4 seconds and then I get activity B opened. I would like to show some animation like circle progress bar or something like that. So is it possible to start activity not in the UI thread?
Here's what I tried so far
new Thread(new Runnable() {
#Override
public void run() {
while (progressStatus < 100) {
progressStatus += 25;
handler.post(new Runnable() {
#Override
public void run() {
//animation code
}
});
try {
Thread.sleep(1600);
if (progressStatus == 100){
Intent intent = new Intent(getActivity(), MapActivity.class);
intent.putExtra("routeId", id);
startActivity(intent);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
However this is not exactly what I need. Any solutions or suggestions?
1) So is it possible to start activity not in the UI thread
Activity should be processed in Main UI Thread only. You will not be able to start an activity in other threads. Even after processing data in background thread, for invoking or pushing an activity methods like runOnUiThread is used
If you are performing long operations in main thread, Android will throw ANR
2) However this is not exactly what I need. Any solutions or
suggestions?
Now an alternative approach is to do heavy operations of your Activity in background using AsyncTask or IntentService and show progress bar until those operations are completed.
Once this operation is completed, publish the data to your MapActivity.
1) Sample Intent Service implementation
2) Sample AsyncTask example
Sample of AsyncTask on onCreate will be as follows
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new BackAsync().execute("URL");
}
private String getURLDetailsTitle(String url) {
//Retrieve data from external URL
}
//AsyncTask to fetch data from URL called inside onCreate
private class BackAsyncextends AsyncTask<String, String, String> {
#Override
protected String doInBackground(String... urls) {
String str = getURLDetailsTitle(urls[0]);
while(true) {
publishProgress(str);
}
return str;
}
#Override
protected void onProgressUpdate(String... progress) {
//update progress
}
protected void onPostExecute(Long result) {
//update UI changes
}
Use AsyncTask and start progress bar in the doInBackground method and close it in the onPostExecute method.
I have a AsysTask
class myAsyncTask extends AsyncTask<Void, Void, Integer> {
ProgressDialog progDialog;
myAsyncTask() {
}
#Override
protected void onPreExecute() {
super.onPreExecute();
progDialog = ProgressDialog.show(
SwitchArticle.this,
"Loading",
"Pleasewait",
true,
true,
new DialogInterface.OnCancelListener(){
#Override
public void onCancel(DialogInterface dialog) {
myAsyncTask.this.cancel(true);
}
}
);
}
#Override
protected Integer doInBackground(Void... arg0) {
// Call a function load Data Json...
return 1;
}
#Override
protected void onProgressUpdate(Void... values) {
// TODO Auto-generated method stub
super.onProgressUpdate(values);
}
#Override
protected void onPostExecute(Integer result) {
super.onPostExecute(result);
if (result != 1) {
progDialog.dismiss();
Toast.makeText(
SwitchArticle.this,
"Error Load Data",
Toast.LENGTH_SHORT).show();
}
else
{
//.. Bind Data To Adapter
}
progDialog.dismiss();
}
}
Call in Oncreate function :
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myAsyncTask ma = new myAsyncTask();
ma.execute();
}
The first time, this code is load data and bind to listview very good.
then, i press back other activity,and comback this activity call asyntask, this code run very good.
After i back to other activity , and finish this activity call this asysntask. I press lock screen device and wait about 5 minute. i unlock device and come back activity call this asysntask. myAsynTask run doInBackGround and NOT run to onPostExcute to bind data to ListView.
Sorry because my English is very poor. I'm Vietnamese.
I think onCreate is called when you unlock the screen and go back to your activity. That means your AsyncTask will start running again... Hope that helps
How to display progressbar i'm calling intent from class A to class B.
In which class B lloads the data from the using parsing mean while
this happens i'm getting blank screen in this time i'd like to show
progressbar how can i do that.
Right now i'm writing the code as follows..
class A extends Activity{
oncreate(){
...
Button b1 = (Button) findViewById(R.id.button1);
b1.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
new performBackgroundtask().execute();
}
}
class performBackgroundtask extends AsyncTask<Void, Void, Void> {
//
ProgressDialog progressDialog = new ProgressDialog(Main.this);
#Override
protected void onPreExecute() {
progressDialog = ProgressDialog.show(Main.this,"", "Please wait...");
super.onPreExecute();
/*
* progressDialog.setMessage("Please wait while loading ...");
* progressDialog.show(); progressDialog.setCancelable(true);
*/
}
#Override
protected Void doInBackground(Void... params) {
Intent in = new Intent(A.this, B.class);
startActivity(in);
// TODO Auto-generated method stub
return null;
}
#Override
protected void onPostExecute(Void result) {
progressDialog.dismiss();
}
}
}
class B { ...
/*
* In which this class has another view which has to get the data from
* URL using SAXPArsing.
*
* ... for this where i need to write progress bar code.
*/
}
I've done something similar using a handler. When the handler recieves it's response from a thread, you can dismiss your progressdialog.
Some code to help you understand:
final Handler handler = new Handler()
{
#Override
public void handleMessage( Message message )
{
progressBar.setVisibility( View.GONE );
// My irrelevant code here
}
};
new Thread( new Runnable()
{
public void run()
{
// Do your stuff here
Message message = handler.obtainMessage( 1, text );
handler.sendMessage( message );
}
}).start();
Instead of calling another Activity class to do your downloading, move this functionality into another class that each Activity can use.
I have my asyncTask run when the activity first starts, then if network connectivity is not available then i have a refresh button that tries to run the asyncTask to try again. But i get a debug error saying this..
07-29 18:14:21.290: ERROR/AndroidRuntime(9080): FATAL EXCEPTION: main
07-29 18:14:21.290: ERROR/AndroidRuntime(9080): java.lang.IllegalStateException: Cannot execute task: the task has already been executed (a task can be executed only once)
07-29 18:14:21.290: ERROR/AndroidRuntime(9080): at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:541)
07-29 18:14:21.290: ERROR/AndroidRuntime(9080): at android.os.AsyncTask.execute(AsyncTask.java:499)
07-29 18:14:21.290: ERROR/AndroidRuntime(9080): at com.fttech.gameIT.MainMenu$1.onClick(MainMenu.java:90)
Is there anyway to run this twice?
Just create another instance and execute it.
Just like threads, AsyncTasks can't be reused. You have to create a new instance every time you want to run one.
You can never execute a thread again, not in Java, not in any other language, once the thread is done with the run() method, you cannot restart it, which is why you are getting the IllegalStateException.
You can however still call the methods on that thread but they will run on the thread that is calling them NOT on a different thread. Therefore you will have to create a new one.
You cannot run same instance of an AsyncTask more than once.
Let's assume you have an AsyncTask named MyAsyncTaks and you intend to do something like this,
MyAsyncTask myAsyncTask = new MyAsyncTaks();
myAsyncTask.execute(); // Works as expected
.
.
.
.
myAsyncTask.execute(); // This will throw you exception
The reason for this is, a thread once finishes its 'run' method, cannot be assigned another task. Here, on the first invocation of execute(), your AsyncTask started running and
after doing its job, the thread comes out of run. Naturally, next invocation of execute() will throw you exception.
The simplest way to run this more than once is to create a new instance of MyAsyncTaks and call execute on that.
MyAsyncTask myAsyncTask = new MyAsyncTaks();
myAsyncTask.execute(); // Works as expected
.
.
.
MyAsyncTask myAsyncTask2 = new MyAsyncTaks();
myAsyncTask2.execute(); // Works as expected
Though its not needed to be mentioned here, one must be aware that post Android SDK version Honeycomb, if your run more than one AsyncTask at once, they actually run
sequentially. If you want to run them parallally, use executeOnExecutor instead.
Just make a new call like new asyncTask().execute(); You must create a new object to restart that task.
I just create the asynctask then create a runnable that creates new instances of the asynctask. Then you can submit your runnable over and over again to the handler.
class MyAsyncTask extends AsyncTask<String, Void, String>{ ...}
Runnable myRunner = new Runnable(){
public void run() {
new MyAsyncTask ().execute(...);
}};
myHandler.post(myRunner);
This solved my problem:
public class MainActivity extends AnimationActivity {
MyAsyncTasks asyncTasks = new MyAsyncTasks();
#BindView(R.id.refresh_btn)
Button refreshBtn;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setUnbinder(ButterKnife.bind(this)); // ButterKnife usage
syncTasks(); // run asyncTasks on activity start
refreshBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
syncTasks(); // run asyncTasks on button click
}
});
}
private void syncTasks() {
try {
if (asyncTasks.getStatus() != AsyncTask.Status.RUNNING){ // check if asyncTasks is running
asyncTasks.cancel(true); // asyncTasks not running => cancel it
asyncTasks = new MyAsyncTasks(); // reset task
asyncTasks.execute(); // execute new task (the same task)
}
} catch (Exception e) {
e.printStackTrace();
Log.e("MainActivity_TSK", "Error: "+e.toString());
}
}
}
You can do it like this :
private MyAsyncTask createAsyncTask(){
if (myAsyncTask == null){
return myAsyncTask = new MyAsyncTask();
}
myAsyncTask.cancel(true);
return myAsyncTask = new MyAsyncTask();
}
and then you can use it :
createAsyncTask().execute();
this make a new instance of your background task everytime.
Async tsk only run once as the Exceptions says the task has already been executed..
So you just have to make a new instance of async and then call .execute();
in order to run it again .. thank you
I created an Arraylist of type ProgressUpdater(Name of class which extends AsyncTask) and added the instances into it(in the onClick of a button). So you can execute and cancel these task when needed.
public class MainActivity extends Activity {
ProgressBar progress;
ProgressUpdater task;
ArrayList<ProgressUpdater> pu = new ArrayList<MainActivity.ProgressUpdater>();
int count = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
progress = (ProgressBar) findViewById(R.id.progress);
}
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn:
task = new ProgressUpdater();
pu.add(task);
count++;
pu.get(count - 1).execute(0);
System.out.println("task" + task);
// task.execute(10);
break;
case R.id.btnCancel:
if (count >= 0) {
pu.get(count - 1).cancel(true);
pu.remove(count - 1);
count--;
}
// task.cancel(true);
break;
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
private class ProgressUpdater extends AsyncTask<Integer, Integer, Void> {
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
progress = (ProgressBar) findViewById(R.id.progress);
progress.setMax(100);
}
#Override
protected Void doInBackground(Integer... params) {
// TODO Auto-generated method stub
int start = params[0];
for (int i = start; i <= 100; i++) {
try {
boolean cancelled = isCancelled();
if (!cancelled) {
publishProgress(i);
SystemClock.sleep(100);
}
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
#Override
protected void onPostExecute(Void result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
Log.v("Progress", "Finished");
}
#Override
protected void onCancelled() {
// TODO Auto-generated method stub
super.onCancelled();
progress.setMax(0);
}
#Override
protected void onProgressUpdate(Integer... values) {
// TODO Auto-generated method stub
super.onProgressUpdate(values);
progress.setProgress(values[0]);
}
}
}
in your MainActivity you can put so this:
LeoAsyncTask leoAsyncTaskGeneric;
public void onClick_AsyncTask(View view) {
LeoAsyncTask leoAsyncTaskInner = new LeoAsyncTask();
leoAsyncTaskInner.execute();
leoAsyncTaskGeneric=leoAsyncTaskInner;
}
/**if you create a space in memory of your AsyncTask class as a generic, then you can create an instance of that same class within the onClick method, and there the equals, so every time you press onClick you will be using a new instance of the Class AsyncTask, it will not give you problems
*/
You could cancel your asyncTask when you press the button and then execute it again.
Inside OnClic method:
asyncTask.cancel();
AsyncTask asyncTask = new AsyncTask();
asyncTask.execute();
#coder_For_Life22 I think am late for the answer ,anyway you can do like
#Override
protected void onPostExecute(Void a) {
myAsyncTask=new MyAsyncTask();
}
in order to start a new AsyncTask after execution :)