I'm trying to do the simple act of hiding/showing ProgressBar according to AsyncTask state ,
I have two classes one extends FragmentActivity and second AsyncTask.
MainActivity.java
public class MainActivity extends FragmentActivity {
public static ProgressBar mProgressBar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mProgressBar = (ProgressBar) findViewById(R.id.progress_bar);
}
#Override
protected void onStart() {
super.onStart();
// What will happen to the progress bar here?
}
#Override
protected void onStop() {
super.onStop();
// What will happen to the progress bar here?
}
#Override
protected void onResume() {
super.onResume();
// What will happen to the progress bar here?
}
}
MyAsyncTask.java
public class MyAsyncTask extends AsyncTask<Void,Void, Void> {
#Override
protected Void doInBackground() {
// start download some images from cloud
// Here the progress bar should start to appear in MainActivity
// mProgressBar.setVisibility(View.VISIBLE);
}
#Override
protected void onPostExecute(Void result) {
Log.d(TAG, "Finished book downloading images the cloud");
// Here the progress bar should start to disappear in MainActivity
// mProgressBar.setVisibility(View.GONE);
}
}
main_activity.xml
<ProgressBar
android:id="#+id/progress_bar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminate="true" />
Hope you understand me, thank to everyone who can help.
The progress bar should appear in onPreExecute() method (still in UI thread). Then you dismiss it when you get back to UI thread in onPostExecute method.
public class MyAsyncTask extends AsyncTask<Void,Void, Void> {
#Override
protected void onPreExecute(Void result) {
Log.d(TAG, "Finished book downloading images the cloud");
// Here the progress bar should start to disappear in MainActivity
mProgressBar.setVisibility(View.VISIBLE);
}
#Override
protected Void doInBackground() {
// start download some images from cloud
// there is a time cost operation
}
#Override
protected void onPostExecute(Void result) {
Log.d(TAG, "Finished book downloading images the cloud");
// Here the progress bar should start to disappear in MainActivity
// mProgressBar.setVisibility(View.GONE);
}
}
You should use onPreExecute() method to show the dialog.
Here is MainActivity
#Override
protected void onResume() {
super.onResume();
new MyAsyncTask().execute();
}
I think you should read APIs first.
Use preExecute and postExecute methods as they run on UI thread.
public class MyAsyncTask extends AsyncTask<Void,Void, Void> {
ProgressBar pBar;
#Override
protected void onPreExecute(Void result) {
pBar=new ProgressBar(getContext());
pBar.show();
}
#Override
protected void onPostExecute(Void result) {
if(pBar !=null and pBar.isShowing()){
pBar.dismiss();
}
}
}
Use interface in Asyntask class for communicate with Activity class
public class MyAsyncTask extends AsyncTask<Void,Void,Void> {
//use context for activity reference
private Context context_;
public MyAsyncTask(Context context) {
this.context_=context;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... voids) {
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
if(mCallBack!=null ){
mCallBack.onSuccess("Success");
}else {
mCallBack.onError("Error");
}
}
MyAsyncCallBack mCallBack=null;
public MyAsyncCallBack getmCallBack() {
return mCallBack;
}
public void setmCallBack(MyAsyncCallBack mCallBack) {
this.mCallBack = mCallBack;
}
public interface MyAsyncCallBack{
public void onSuccess(String successMessage);
public void onError(String successMessage);
}
}
Call AsynckTask Class from activity class.Before calling asyntask start progress. and after completing work in asyntask return activity via interface and hide progress.
startProgress();
MyAsyncTask mTask=new MyAsyncTask(YourActivity.this);
mTask.setmCallBack(new MyAsyncTask.MyAsyncCallBack() {
#Override
public void onSuccess(String successMessage) {
//do success work and hide progress
hideProgress();
}
#Override
public void onError(String successMessage) {
//do error work and hide progress
hideProgress();
}
});
mTask.execute();
Related
I have a class that is used for various ASyncTasks. Sometimes, I need to hide certain buttons, or views or whatever based upon the Activity or action. The object needing visibility set can vary.
MyAsyncTask
public class MyAsyncTask extends AsyncTask<String, Void, JSONObject> {
private ProgressBar mProgressBar;
public ASynceResponse delegate = null;
public MyAsyncTask() {
this.delegate = delegate;
this.mProgressBar = progressBar;
}
#Override
protected void onPreExecute() {
mProgressBar.setVisibility(View.VISIBLE);
}
#Override
protected JSONObject doInBackground(String... params) {
return;
}
#Override
protected void onPostExecute(JSONObject data) {
mProgressBar.setVisibility(View.GONE);
delegate.processResults(data);
}
public interface ASyncResponse {
void processResults(JSONObject data);
}
}
I usually call it by:
new MyAsyncTask(this, mProgressBar).execute("Something","Something Else",null);
Which I pass in a ProgressBar in the Activity that shows the background action is happening.
But I want more. I want to Overide my classes onPreExecute and onPostExecute to hide/show other items too.
Is that possible?
But I am trying to find a way to Overide the onPreExecute to hide anytype (or many types) views.
Is something like this possible?
MyAsyncTask myAsyncTask = new MyAsyncTask(new onPreExecute(
// hide a view
));
You can do that using interface.
public class MyAsyncTask extends AsyncTask<String, Void, JSONObject> {
private ProgressBar mProgressBar;
public ASynceResponse delegate = null;
public MyAsyncTask() {
this.delegate = delegate;
this.mProgressBar = progressBar;
}
#Override
protected void onPreExecute() {
delegate.myOnPreExecute();
mProgressBar.setVisibility(View.VISIBLE);
}
#Override
protected JSONObject doInBackground(String... params) {
return;
}
#Override
protected void onPostExecute(JSONObject data) {
mProgressBar.setVisibility(View.GONE);
delegate.processResults(data);
}
public interface ASyncResponse {
void processResults(JSONObject data);
void myOnPreExecute();
}
}
Demo class example
class Demo implements ASyncResponse{
.....
void processResults(JSONObject data){
....
}
void myOnPreExecute(){
// do your stuff for pre execute
}
}
I'm trying to get a response back from my public class saveData extends AsyncTask.
I added a public interface but the Android Studio gives me an error for the #Overide on my onCreate in the activity.
public class almostFinish extends Activity implements OnTaskCompleted{
#Override // here I get an Error
protected void onCreate(Bundle savedInstanceState) {}
#Override
public void onTaskCompleted(boolean result) {
//ToDo
}
}
My interface.
public interface OnTaskCompleted {
void onTaskCompleted(boolean isSuccess);
}
My AsyncTask class
public class saveData extends AsyncTask<List<String>, Void, Void> {
private OnTaskCompleted listener;
boolean myflag = false;
#Override
public void onPreExecute() {}
#Override
protected Void doInBackground(List<String>... params) { }
#Override
public void onPostExecute(Void result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
listener.onTaskCompleted(myflag);
}
}
Thanks for any help.
I'm just getting an Error in the editor: "Annotations are not allowed here"
If I remove the #Override then I get an Error telling me to add #Override.
According this code you will get null pointer exception. because you have not assign the listener in code.
public class saveData extends AsyncTask < List < String > , Void, Void > {
private OnTaskCompleted listener;
boolean myflag = false;
#Override
public void onPreExecute() {}
#Override
protected Void doInBackground(List < String > ...params) {}
#Override
public void onPostExecute(Void result) {
super.onPostExecute(result);
onTaskCompleted(myflag);
}
}
Learning what I can from the internet and youtube, I'm sure I am not handling this in the appropriate way. I have an existing app which includes a slide out navigation drawer using fragments. I am now trying to get an activity to run within that fragment without any luck. It works when ran on it's own, but after trying to combine the two, I am not able to get "draftactivity" to run properly. The fragment operates as it should.
public class tapsfragment extends Fragment {
public static tapsfragment newInstance() {
tapsfragment fragment = new tapsfragment();
return fragment;
}
public tapsfragment(){}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
((MainActivity) activity).onSectionAttached(2);
}
public class DraftActivity extends Activity {
TextView draftfeed;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.draft_activity);
draftfeed = (TextView) findViewById(R.id.draftfeed);
new PostAsync().execute();
}
class PostAsync extends AsyncTask<Void, Void, Void> {
ProgressDialog pd;
XMLHelper helper;
#Override
protected void onPreExecute() {
pd = ProgressDialog.show(DraftActivity.this, "Taps", "Loading posts for ******.com ...", true, false);
}
#Override
protected Void doInBackground(Void... arg0) {
helper = new XMLHelper();
helper.get();
return null;
}
#Override
protected void onPostExecute(Void result) {
StringBuilder builder = new StringBuilder();
for (ItemValue post : helper.posts) {
builder.append("\nPost: " + post.getTitle());
builder.append("\n");
}
draftfeed.setText(builder.toString());
pd.dismiss();
}
}
Activity can't run in a fragment, it's the other way around.
In my Activity1, I have an AsyncTask that uploads to the server. Once this task is started, I want to start Activity, without waiting for the completion of AsyncTask. When the AsyncTask from Activity1 is completed, I want to update something in Activity2. After doing some searching, I've found multiple references/examples of using interfaces. But I ran into the following problem:
OnUploadCompleted Interface
public interface OnUploadCompleted {
void on UploadCompleted();
}
Activity2
public class Activity2 extends Activity implements OnUploadCompleted {
// all the usual activity code
#Override
public void onUploadCompleted() {
Toast.makeText(this, "Upload Done", ....
}
}
Activity1
public class Activity1 extends Activity {
// all the usual activity code
private class Upload extends AsyncTask<...> {
OnUploadCompleted listener;
public Upload(OnUploadCompleted listener) {
this.listener = listener;
}
// skipping doInBackground task
#Override
protected void onPostExecute(...) {
super.onPostExecute();
listener.onUploadCompleted();
}
}
void foo (...) {
OnUploadCompleted listener = new Activity2();
Upload upload = new Upload(listener);
upload.execute();
finish();
}
}
The problem I have is in the foo() function. the listener is a new instance of Activity2 class, but Activity2 hasn't been created yet. It will be created by the parent activity of Activity1, after the finish(). So, when the listener is actually called, the activity that it's "connected" to is null. In the onUploadCompleted(), when Toast is called, the "this" is null.
try sending Broadcasts to ACtivity2 from Activity1 when Activity1's AsyncTask completed...
public class MainActivity extends Activity {
public static final String ACTION_TASK_COMPLETED = "com.sample.project.action.ACTION_TASK_COMPLETED";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#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 DoTask extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
// please wait. I am doing work
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
// yay... work completed...
Intent intent = new Intent(ACTION_TASK_COMPLETED);
LocalBroadcastManager.getInstance(MainActivity.this).sendBroadcast(intent);
}
}
}
public class SecondActivity extends Activity {
private TaskReceiver taskReceiver;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
IntentFilter intentFilter = new IntentFilter(MainActivity.ACTION_TASK_COMPLETED);
taskReceiver = new TaskReceiver();
LocalBroadcastManager.getInstance(this).registerReceiver(taskReceiver, intentFilter);
}
#Override
protected void onDestroy() {
super.onDestroy();
LocalBroadcastManager.getInstance(this).unregisterReceiver(taskReceiver);
}
private void onUploadImage() {
// uploading completed...
}
private class TaskReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
onUploadImage();
}
}
}
I have an AsyncTask which shows a ProgressDialog. The AsyncTask is started when the activity is started:
public class MyActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_layout);
new MyTask().execute();
}
// ... other code
private class MyTask extends AsyncTask<Void, Void, Void>{
private ProgressDialog dialog = new ProgressDialog(MyActivity.this);
#Override
protected void onPreExecute() {
dialog.show();
}
#Override
protected Void doInBackground(Void... voids) {
// get data from a server
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
// call to a method in MyActivity which updates the UI.
if (dialog.isShowing()) {
dialog.dismiss();
}
}
}
}
This code works perfectly, untill I rotate my screen. Which makes sense, because the context that was used to create the dialog doesn't exist anymore (because the activity is re-created when rotating), and a window leak is caused.
The only solution I could think of isn't a really nice one: create a static instance of the task and dialog, and simply dismiss the dialog when the activity is destroyed, and recreate the dialog in the oncreate method if the task is still running.
So how would I solve something like this without losing functionality (so the dialog must always be shown when the task is running, and rotating the device should be allowed)?
As Raghunandan suggested in his comment, I looked into Fragments and solved my problem.
I created a Fragment which starts my AsyncTask, as explained in the blogpost that Raghunandan provided.
And to make sure that my Dialog didn't get leaked, I created a DialogFragment, as described here (Basic Dialog).
Here's my working code:
My Activity:
public class MyActivity extends Activity implements MyTaskFragment.TaskCallbacks {
private MyTaskFragment task;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_layout);
FragmentManager fm = getFragmentManager();
task = (MyTaskFragment) fm.findFragmentByTag("myTask");
if (task == null) {
task = new MyTaskFragment();
fm.beginTransaction().add(task, "myTask").commit();
}
}
#Override
public void onPreExecute() {
FragmentTransaction ft = getFragmentManager().beginTransaction();
Fragment prev = getFragmentManager().findFragmentByTag("myDialog");
if (prev != null) {
ft.remove(prev);
}
ft.addToBackStack(null);
StringProgressDialogFragment dialog = StringProgressDialogFragment.newInstance("My message");
dialog.show(ft, "myDialog");
}
#Override
public void onPostExecute() {
StringProgressDialogFragment dialog = (StringProgressDialogFragment) getFragmentManager().findFragmentByTag("myDialog");
if (dialog!=null) {
dialog.dismiss();
}
// update UI
}
// ... other code
}
My Task fragment:
public class MyTaskFragment extends Fragment {
private TaskCallbacks mCallbacks;
private Task mTask;
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
mCallbacks = (TaskCallbacks) activity;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Retain this fragment across configuration changes.
setRetainInstance(true);
// Create and execute the background task.
mTask = new Task();
mTask.execute();
}
#Override
public void onDetach() {
super.onDetach();
mCallbacks = null;
}
private class Task extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
mCallbacks.onPreExecute();
}
#Override
protected Void doInBackground(Void... voids) {
// do stuff
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
mCallbacks.onPostExecute();
}
}
public static interface TaskCallbacks {
void onPreExecute();
void onPostExecute();
}
}
My Dialog fragment:
public class StringProgressDialogFragment extends DialogFragment {
private String message;
public static StringProgressDialogFragment newInstance(String message) {
StringProgressDialogFragment dialog = new StringProgressDialogFragment();
Bundle args = new Bundle();
args.putString("message", message);
dialog.setArguments(args);
return dialog;
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
ProgressDialog dialog = new ProgressDialog(getActivity());
message = getArguments().getString("message");
dialog.setMessage(message);
return dialog;
}
}
New Loaders API can help you (available via support package) - man. They will solve problem with rotation, but not a mem. leak. To solve mem. leaks write your own "AsyncTask" (with a "clearContext" routine) and clear it's context in activity's onDestroy (or onPause, depends on your architecture). It may looks like a bicycle, but the task takes max 1 day, and you will have a full control on all the resources you background worker use.
By the way: consider using dialogs through fragments, because it solves dialog kill on screen rotation.
try with sample. it will work. basically just restrict the oncreate call by handling the config change. this solution may help you.
public class MainActivity extends Activity {
LoadProgrssdata task = new LoadProgrssdata();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toast.makeText(this, "oncreate called", Toast.LENGTH_SHORT).show();
task.execute();
}
public class LoadProgrssdata extends AsyncTask<Void, Void, Void> {
ProgressDialog progressDialog;
//declare other objects as per your need
#Override
protected void onPreExecute()
{
progressDialog= ProgressDialog.show(MainActivity.this, "Progress Dialog Title Text","Process Description Text", true);
//do initialization of required objects objects here
};
#Override
protected Void doInBackground(Void... params)
{
//do loading operation here
try {
Thread.sleep(6000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result)
{
super.onPostExecute(result);
progressDialog.dismiss();
};
}
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Checks the orientation of the screen
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
Log.e("orientation ", "landscape");
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
Log.e("orientation ", "portrait");
}
}
}
and in android manifest file:
<activity
android:name="com.example.MainActivity"
android:label="#string/app_name"
android:configChanges="orientation|keyboardHidden|screenSize" />
I managed to fix this problem by trying to catch any crash that, may occurs, in doInBackground.