I have a button on 6 different Activities. Clicking on that button does almost the same task with different params depending on the Activity.
This will be done using an AsyncTask and in onPostExecute() the button state will be changed.
someButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
new Task().execute("param1", "param2");
}
}
private class Task extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
//background task using params[0], params[1]
return "success" or "error";
}
#Override
protected void onPostExecute(String result) {
if (result == "success") {
//change the someButton state
}else{
//show an error message
}
}
Instead of having the same AsyncTask in all the 6 Activities, how can I use a single Asynctask from all the Activities and change the respective view?
You should create Task, with methods onSuccess, onFailure and override them.
public class Task extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
//background task using params[0], params[1]
return "success" or "error";
}
#Override
protected void onPostExecute(String result) {
if (result == "success") {
onSuccess(result);
}else{
onFailure(result);
}
}
protected void onSuccess(String result) {};
protected void onFailure(String result) {};
}
and then in activity use it like this:
someButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
new Task(){
#Override
protected void onSuccess(String result){
// do what you want
}
#Override
protected void onFailure(String result){
// do what you want
}
}.execute("param1", "param2");
}
}
Put your Task in its own file and make it public.
Create a callback interface:
public interface TaskCallback {
public void onSuccess(String result);
public void onFailure(String errorMessage);
}
Give such a callback to your Task:
public class Task extends AsyncTask<String, Void, String> {
private TaskCallback callback;
public Task(TaskCallback callback) {
this.callback = callback;
}
#Override
protected String doInBackground(String... params) {
//background task using params[0], params[1]
return "success" or "error";
}
#Override
protected void onPostExecute(String result) {
if (result == "success") {
callback.onSuccess(result);
} else{
callback.onFailure(errorMessage);
}
}
}
And then implement the callback when creating the Task instance in your activity:
someButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
private TaskCallback callback = new TaskCallback() {
#Override
public void onSuccess(String result) {
//change the someButton state
}
#Override
public void onFailure(String errorMessage) {
//show an error message
}
}
new Task(callback).execute("param1", "param2");
}
}
Related
I have a progress dialog that shows how many files are left for uploading in my Async Task and the user can dismiss this dialog if he wants to. However I want to have a button that will be able to show again that progress dialog at its current stage and I don't know how to do that since you I can't just create a function in the Async Task and call it from a different activity. Any thoughts?
You can make a singleton class to handle the Async Task progress which holds only one listener (the Activity who wants to listen for the progress of your AsyncTask).
Your Singleton class can be like below:
public class ProgressDialogUtil {
public interface ProgressDialogUtilListener{
void showProgressDialog();
void dismissProgressDialog();
void updateProgressDialog(int value);
void setProgressDialogMessage(String message);
}
private ProgressDialogUtilListener listener;
private static ProgressDialogUtil mInstance;
public static ProgressDialogUtil getInstance() {
if (mInstance == null) {
synchronized (ProgressDialogUtil.class) {
if (mInstance == null) {
mInstance = new ProgressDialogUtil();
}
}
}
return mInstance;
}
public void setListener(ProgressDialogUtilListener listener) {
this.listener = listener;
}
public void showProgressDialog(){
if(listener!=null)
listener.showProgressDialog();
}
public void dismissProgressDialog(){
if(listener!=null)
listener.dismissProgressDialog();
}
public void updateProgressDialog(int value){
setProgressDialogMessage("Files Downloaded: "+ value);
if(listener!=null)
listener.updateProgressDialog(value);
}
public void setProgressDialogMessage(String message){
if(listener!=null)
listener.setProgressDialogMessage(message);
}
}
Then you can use this Singleton class (ProgressDialogUtil) in your AsyncTask like below to inform for any update occurred:
public class MyAsyncTask extends AsyncTask<Void, Integer, Boolean> {
public final ProgressDialogUtil progressDialogUtil;
public MyAsyncTask(ProgressDialogUtil progressDialogUtil){
this.progressDialogUtil = progressDialogUtil;
}
#MainThread
#Override
protected void onPreExecute() {
super.onPreExecute();
progressDialogUtil.setProgressDialogMessage("Start Download files..");
progressDialogUtil.showProgressDialog();
}
#WorkerThread
#Override
protected Boolean doInBackground(Void... params) {
//download your files here in the Background Thread...
//below is a sample loop
for (int i=0; i <= 50; i++) {
try {
Thread.sleep(1000);
publishProgress(i);
} catch (InterruptedException e) {
e.printStackTrace();
return false;
}
}
return true;
}
#MainThread
#Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
progressDialogUtil.updateProgressDialog(values[0]);
}
#MainThread
#Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
progressDialogUtil.setProgressDialogMessage("Finished Download!");
progressDialogUtil.dismissProgressDialog();
}
}
Then in your first Activity where you start the AsyncTask you can create a new instance of your Progress Dialog and set a listener ProgressDialogUtilListener to listen for any AsyncTask progress to show/hide/update the Progress Dialog like below:
ProgressDialog pd = new ProgressDialog(this);
ProgressDialogUtil progressDialogUtil = ProgressDialogUtil.getInstance();
progressDialogUtil.setListener(new ProgressDialogUtil.ProgressDialogUtilListener()
{
#Override
public void showProgressDialog() {
if (!pd.isShowing())
pd.show();
}
#Override
public void dismissProgressDialog() {
if (pd.isShowing())
pd.dismiss();
}
#Override
public void updateProgressDialog(int value) {
pd.setProgress(value);
}
#Override
public void setProgressDialogMessage(String message) {
pd.setMessage(message);
}
});
new MyAsyncTask(progressDialogUtil).execute();
Finally when you navigate to a new Activity you can use the same Singleton Instance ProgressDialogUtil and change the listener to the new Activity now all AsyncTask events will be handled to the new Activity and the dialog can be opened/closed via a button through this singleton class like below:
ProgressDialog pd = new ProgressDialog(this);
ProgressDialogUtil progressDialogUtil = ProgressDialogUtil.getInstance();
progressDialogUtil.setListener(new ProgressDialogUtil.ProgressDialogUtilListener()
{
#Override
public void showProgressDialog() {
if (!pd.isShowing())
pd.show();
}
#Override
public void dismissProgressDialog() {
if (pd.isShowing())
pd.dismiss();
}
#Override
public void updateProgressDialog(int value) {
pd.setProgress(value);
}
#Override
public void setProgressDialogMessage(String message) {
pd.setMessage(message);
}
});
//Show Progress Dialog from a Button Click
showButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
progressDialogUtil.showProgressDialog();
}
});
//Dismiss Progress Dialog from a Button Click
dismissButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
progressDialogUtil.dismissProgressDialog();
}
});
You can have a Live data in any singleton class like below to share the progress between activities.
object ProgressHelper {
val progress = MutableLiveData<Int>()
}
Then update the progress values from the AsyncTask like below:
override fun onProgressUpdate(vararg values: Int?) {
super.onProgressUpdate(*values)
ProgressHelper.progress.value = 100
}
In your activity you can observe the progress like below:
ProgressHelper.progress.observe(this, Observer {
val progress = it
})
I am trying to use AsyncTask but both my doInBackground and onPostExecute methods give me the same error saying Method does not override method from its superclass. My code is:
public class SigninActivity extends AsyncTask{
private TextView status, result;
private Context context;
private int flag = 0;
public SigninActivity(Context context, TextView status, TextView result, int flag) {
this.context = context;
this.statusField = status;
this.roleField = result;
this.flag = flag;
}
protected void onPreExecute() {
}
#Override
protected String doInBackground(String... arg0) {
//Code
}
#Override
protected void onPostExecute(String result) {
//Code
}
You should create AsyncTask with three parameters < X,Y,Z >. For more details in here
private class MyAsyncTask extends AsyncTask<String, String, String> {
#Override
protected String doInBackground(String... params) {
// your code
}
#Override
protected void onPostExecute(String result) {
//your code
}
#Override
protected void onPreExecute() {
//your code
}
#Override
protected void onProgressUpdate(String... text) {
// your code
}
}
I want to publish the result of my AsyncTask (a string) in a textView.
Here is my Main:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ReadRss readRss=new ReadRss(this);
readRss.execute();
......
}
Here is my AsyncTask:
public class ReadRss extends AsyncTask<Void,Void,Void> {
public ReadRss(Context context){
}
#Override
protected void onPreExecute() {
}
#Override
protected void onPostExecute(Void aVoid) {
}
#Override
protected Void doInBackground(Void... params) {
ProcessXml();
return null;
}
private void ProcessXml() {
//HERE CREATE MY STRING
String myresult="example";
TextView txt_ris = (TextView)findViewById(R.id.txt_ris); <---HOW CAN I DO THIS?
txt_ris.setText(myresult);
}
}
}
}
FindViewById don't work in the AsyncTask so how can i get the TextView in here?
Maybe i can pass it as a paramiter in the AsyncTask, What is the syntax?
You need to place UI work in onPostExecute method, since doInBackground executes in not UI thread
public class ReadRss extends AsyncTask<Void,Void,String> {
public ReadRss(Context context){
}
#Override
protected void onPreExecute() {
}
#Override
protected void onPostExecute(String string) {
TextView txt_ris = (TextView)findViewById(R.id.txt_ris);
txt_ris.setText(myresult);
}
#Override
protected String doInBackground(Void... params) {
return ProcessXml();
}
private String ProcessXml() {
//HERE CREATE MY STRING
return "example";
}
}
For your TextView to be correctly referenced you need a context and you already have a reference to your starting Activity in your AsyncTask constructor, so you can do something like:
public class ReadRss extends AsyncTask<Void,Void,Void> {
private TextView tv;
private YourStartingActivity activity;
public ReadRss(Context context){
activity = (YourStartingActivity)context;
tv = (TextView)activity.findViewById(R.id.txt_ris)
}
#Override
protected void onPreExecute() {
...
}
#Override
protected void onPostExecute(Void aVoid) {
(follow Michael Spitsin instructions here)
}
#Override
protected Void doInBackground(Void... params) {
...
}
}
I want a selection of methods to only be run on a specific thread:
new Thread("SpecificThread") {
#Override
public void run() {
Looper.prepare();
sSpecificThreadHandler= new Handler();
Looper.loop();
}
}.start();
Is there any notation which would I be able to use? Such as #WorkerThread(thread="SpecificThread")
`#WorkerThread(thread="SpecificThread")`
public void doSomething() {
}
use asynctask they are better than threads.
private class AsyncTaskRunner extends AsyncTask<String, String, String> {
#Override
protected String doInBackground(String... params) {
}
#Override
protected void onPostExecute(String result) {
}
#Override
protected void onPreExecute() {
}
#Override
protected void onProgressUpdate(String... text) {
}
}
use like this:
new AsyncTaskRunner().execute();
if you want async task to complete without moving forward than use get after execute method
My program needs to take in a user's name as a String, and makes a call to the API to see if it exists. I made a method that takes in that string, and executes an async task to send the API call. But it looks like the comparison in my method is being executed before my async task finishes. What is the proper way to implement something like this
public boolean checkUser(String name) {
checkedName = name;
checkValidSummoner check = new checkValidSummoner();
check.execute();
if (checkedName == null) {
return false;
} else {
return true;
}
}
private class checkValidSummoner extends AsyncTask<String, Void, Void> {
#Override
protected void onPreExecute() {
}
#Override
protected Void doInBackground(String... strings) {
try {
checkedName = RiotAPI.getSummonerByName(checkedName).toString();
} catch (APIException e) {
checkedName = null;
}
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
}
}
You can't do that.
Please use listener.
public boolean checkUser(String name, OnCheckValidEndListener listener) {
checkedName = name;
checkValidSummoner check = new checkValidSummoner(listener);
check.execute();
}
public interface OnCheckValidEndListener {
void onCheckValidEnd(String checkedName);
}
private class checkValidSummoner extends AsyncTask<String, Void, Void> {
private final OnCheckValidEndListener listener;
checkValidSummoner(OnCheckValidEndListener listener) {
this.listener = listener;
}
#Override
protected void onPreExecute() {
}
#Override
protected Void doInBackground(String... strings) {
try {
checkedName = RiotAPI.getSummonerByName(checkedName).toString();
} catch (APIException e) {
checkedName = null;
}
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
listener.onCheckValidEnd(checkedName);
}
}
And please use flowing code
checkUser("jon",new OnCheckValidEndListener() {
#Override
public void onCheckValidEnd(String checkedName) {
if (checkedName == null) {
// invalid
} else {
// valid
}
}
});