I have an application with the following workflow :
Main activity where the user types his research keywords -> Click on the "search" button -> Starting an AsyncTask making a query on a webservice (query handled within the doInBackground method) -> Creation of a new activity.
Now I want to display the webservice result within this new activity. How can I do ? I know I should to use "onPostExecute" but the AyncTask object has not any access to this new Activity from the "onPostExecute" method. Any clues ?
Thank you !
How to access to GUI elements from OnPostExecute
Make a activity and get the view in onCreate(bundle) and Define a AsyncTask as inner class.
public class MainActivity extends Activity
{
TextView textView;
public void onCreate(Bundle bundle){
....
textView = (TextView)findViewById(R.id.textview);
}
Declare the AsyncTask inside this class.
private class UpdateUiAsyncTask extends AsyncTask<Void, Void, Void>{
........
.....
protected void onPostExecute(String result) {
textView.setText(result);
}
}
}
Related
Here is the scenario that I am trying to resolve. I have a Layout which contains some data to be submitted to a server, this Activity layout needs to upload multiple files (Attachments) which are listed using RecyclerView.Adapter. In each attachment that is listed in bottom part of my layout is a progress bar that shows status or the percentage of the file that has been uploaded to the sever. On the click of the submit button, it calls an AsyncTask and in the onPostExecute method of this Activity layout I want to upload my attachments.
What is the best way to overcome this issue? Please help.
If your async task is an inner class of an activity or fragment, you can simply call a method that lives in the activity or fragment from within onPostExecute
class MyActivity extends Activity
{
public void showOrHideProgress(Result result)
{
// your code here
}
class MyAsyncTask extends AsyncTask
{
private final WeakReference><View> progressBarReference;
public MyAsyncTask(#NonNull View progress)
{
this.progressBarReference = new WeakReference<>(progress);
}
#Override
protected void onPostExecute(Result result)
{
super.onPostExecute(result);
showOrHideProgress(result); // or do something with progressBarReference
}
}
}
I have two Activitys (mainActivity & downloadActivity) and I have 2 AsyncTasks in downloadActivity
In downloadActivity first it execute getFileAsyncTask for reading a JSON file for adding some images and create a ListView from images, if user clicks on an image, the downloadAsyncTask was called and it starts to download something from the internet.
My problem is here: when the second AsyncTask is running I go back to mainActivity and comeback again to downloadActivity the first AsyncTask wasn't called until the downloadAsyncTask completed.
public class downloadActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
...
new getFileAsyncTask().execute();
...
}
private class getFileAsyncTask extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
//fetch a json file from internet and add images in ListView
return null;
}
}
//there is a Base Adapter class
//if user clicks on an image it calls this downloadAsyncTask.execute()
private class downloadAsyncTask extends AsyncTask<Void, Integer, Void> {
#Override
protected void onPreExecute() {
//download the file
}
}
#Override
protected Void doInBackground(Void... unused) {
//download the file
}
}
note: I want to write something like shopping apps. For example, user can download file and surf into shop to see products .
If you want to run multiple AsyncTasks in parallel, you can call executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR) instead of execute() on your task. By default, AsyncTasks run in serial, first come first serve.
Be careful that the two threads do not interact on the same data, this can cause some strange and hard to trace errors.
you can make it in one asynk class that have two methodes first fetch json file wait response in doInBackground ... if it is ok call download file methode. Those methodes will return an httpResponse object
You can override onBackPressed function in activity and finish the current activity before go to previous activity. When again you come to downloadActivity it call it's oncreate method and call first AsynctTask.
Make one class task like:
Declare progress bar globally in main thread.
Now what you have to do is start one async task in main thread like:
public class myactivity extends Activity {
private ProgressDialog _dialog;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.base_screen);
new abc().execute();
}
class abc extends AsyncTask(String,String,String) {
#Override
protected void onPreExecute() {
_dialog = new ProgressDialog(_ctx);
_dialog.setCancelable(false);
_dialog.setMessage("Loading");
_dialog.show();
super.onPreExecute();
}
#Override
protected String doInBackground(String... params) {
#Override
protected void onPostExecute(String result) {
// in post execute of this class you can run a new thread of your downaloder thread. and in post execute of last thread you have to dismiss the progess bar.
new download activity.execute();
}
}
}
}
}
By the time android apps onStart(),it would execute HttpRequestTask. I have done this part and it works fine.
After the apps open and display data,needs to click on a submit button to POST some data to spring rest web service.In my mind,I think I might need to write another extends AsyncTask ,doInBackground and onPostExecute
What should I code so that system could differentiate extends AsyncTask ,doInBackground and onPostExecute within same Activity?
protected void onStart(){
super.onStart();
new HttpRequestTask().execute();
}
private class HttpRequestTask extends AsyncTask<Void, Void, ArrayList<Item>> {
#Override
protected ArrayList<Item> doInBackground(Void... params) {
//....some code
}
#Override
protected void onPostExecute(ArrayList<PickerItemDetail> pickerList) {
//.....come code and logic
}
}
My app is crashing. What am I doing wrong?
I am using an AsyncTask in a class fetchsSchools.
public class fetchSchools extends AsyncTask<Void, Void, ArrayList<String>>{
#Override
protected ArrayList<String> doInBackground(Void... arg0) {
ArrayList<School> schools = new ArrayList<School>();
ArrayList<String> schoolNames = new ArrayList<String>();
... code omitted for conciseness...
return schoolNames;
}
In this class I have an onPost Execute, my code gets to this, if I remark out the cls2 lines my app runs:
public void onPostExecute(ArrayList<String> schoolNames) {
MainActivity cls2=new MainActivity();
cls2.updateSpinner(schoolNames);
cls2.switchScreens();
}
The above fires off these two outines back in MainActivity which crash the app:
public void updateSpinner(ArrayList<String> schoolNames) {
Spinner schoolSpinner = (Spinner)findViewById(R.id.school_spinner);
schoolSpinner.setAdapter(new ArrayAdapter<String>(this,
android.R.layout.simple_spinner_dropdown_item, schoolNames));
}
public void switchScreens() {
ProgressBar progressBar1 = (ProgressBar)findViewById(R.id.progressBar1);
progressBar1.setVisibility(View.GONE);
TextView loading_label = (TextView)findViewById(R.id.loading_label);
loading_label.setVisibility(View.GONE);
}
Eclipse isn't showing any coding errors. Am I creating and acting on these variables correctly?
Though you have not given code for MainActivity and logcat. Seeing your code looks like MainActivity extends Activity. If so you cannot call
MainActivity cls2=new MainActivity();
MainActivity has to be initialized by android framework with appropriate context. Calling constructor yourself will not call any lifecycle methods of the Activity.
So all subsequent calls that use Context will fail, especially findViewByid
You need to do startActivity instead of what you are doing.
Edit:
Create a constructor in Asynctask pass MainActivity when instantiating and assign like below and remove new MainActivity line
public class fetchSchools extends AsyncTask<Void, Void, ArrayList<String>>{
MainActivity cls2;
fetchSchools(MainActivity activity){
cls2 = activity;
}
#Override
protected ArrayList<String> doInBackground(Void... arg0) {
ArrayList<School> schools = new ArrayList<School>();
ArrayList<String> schoolNames = new ArrayList<String>();
... code omitted for conciseness...
return schoolNames;
}
public void onPostExecute(ArrayList<String> schoolNames) {
cls2.updateSpinner(schoolNames);
cls2.switchScreens();
}
}
In MainActivity, you call
new fetchSchools(mMainActivity).execute(param);
If this is a seperate class from that your main activity, then you're trying to findViewById from where? You probably get NullPointerException on very first line of onPostExecute which is this one:
cls2.updateSpinner(schoolNames);
Because you try to find a view in this method. But you do not have any parent view which contains the view that you seek to find.
So i would suggest you to move this fetchSchools class as a private inner class of your mainActivity. so you'll be able to find those views globally and set them however you want.
This maybe a stupid idea, but does anyone know is it possible to access one activity's object form other places?
To be specific, lets say if you have an activity A (with a textView t) and you create a normal java class B.
At onCreate, you start to run B for some calculation like below,
public class MyActivity extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
t = (TextView)findViewById(R.id.outputtext);
Somejava B = new Somejava();
B.run();
}
}
Is there a way for B to update the textView?
I know the simple way (maybe the correct way) is to return the result from B class and use t.setText(result) in MyActivity, but I'm just want to know is it possible to update the textview in B?
Use Intent or public static variables
can simply pass activity refernce to b in constructor and create the method in your acitivty to update textview. if you using another thread not forgot to use handler or other ways to update UI thread.
Yes, it is possible if the Activity's field is public and post the UI changes in a public Handler created on the first Activity but in facts, it's really ugly to do that...
You can use startActivityForResult(...) to notify an other activity how the process has passed with some serialiezable data in the Bundle extras of the Intent and catch the result in the overrided method onActivityResult(...)...
For a "normal java class" B I would work with interfaces
public interface SomejavaListener{
void onSomejavaFinish(Object result);
}
public class MyActivity implements SomejaveFinish extends Activity {
TextView t;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
t = (TextView)findViewById(R.id.outputtext);
Somejava B = new Somejava();
B.run(MyActivity.this); //notice the extra argument!
}
public void onSomejavaFinish(Object result){
t.setText("updated! ^,^");
}
}
public class Somejava {
//...
public void run(SomejavaListener callback){
//working working
callback.onSomejavaFinish( new Object() );
}
}
However in respect to the android environment the question is sitting in I got the feeling maybe an AsyncTask would be the right thing for you. It has an doInBackground method to do work and not spoiling your UI Thread (resulting in ANR Errors.)
Another advantage is the onPreExecute and onPostExecute methods are running in the UI Thread itself again, so it just takes a blink to update your TextView
public class MyActivity extends Activity {
TextView t;
private class MyAsyncTask extends AsyncTask<Void, Void, Void> {
protected Void doInBackground(Void... void) {
//do your stuff
return null
}
protected void onPostExecute(Void void) {
MyActivity.this.t.setText("updated ^^v");
}
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
t = (TextView) findViewById(R.id.outputtext);
MyAsyncTask myAsyncTask = new MyAsyncTask();
myAsyncTask.execute();
}
}