0

I have a splash screen with a TextView to displays what the app is doing such as "Updating Library"... "Updating Shipping"... etc. I'm using AsyncTask to updated my database via an API.

I'm passing the update text to the AsyncTask. I need to change the text in TextView statusMessage. I'm attempting to do this:

public class JSONParser extends AsyncTask<String, String, JSONObject> {

    static InputStream is = null;
    static JSONObject json = null;
    static String outPut = "";

    TextView statusMessage;

    @Override
    protected void onPreExecute() {
        statusMessage = (TextView) findViewById(R.id.statusMessage);

    }

...

My plan is to change the text in the doInBackground method but findViewById isn't accessible in AsyncTask. I think I need to use setContentView to allow findViewById to work but I'm not sure how.

My java file is SplashScreen.java and my xml is activity_splash_screen.xml

----- EDIT -----

For more info I have three pieces talking to each other:

SplashScreen.java -> calls to method in baseActivity.java -> method sends data to JSONParser.java -> sends parsed JSON from the API to baseActivity.java to update database

Per suggestions below I've declared

statusMessage = (TextView) findViewById(R.id.statusMessage);

In baseActivity.java's onCreate since it's the file calling the AsyncTask.

In JSONParser.java I've done this, now:

public class JSONParser extends AsyncTask<String, String, JSONObject> {

    static InputStream is = null;
    static JSONObject json = null;
    static String outPut = "";

    TextView statusMessage;

    @Override
    protected JSONObject doInBackground(String... params) {
        // TODO Auto-generated method stub
    ...
    }


    protected void onProgressUpdate() {
        statusMessage.setText("testing");
     }

    protected void onPostExecute(JSONObject result) {


    }
}

I'm just using "testing" there for testing purposes.

dcp3450
  • 10,959
  • 23
  • 58
  • 110
  • You could use a Handler to update the TextView (need to post update on the UI thread). – mbmc Jan 13 '14 at 19:00

4 Answers4

3

My plan is to change the text in the doInBackground

Bad plan! You can't update the UI from a background Thread. You will need to do this in either onPostExecute() or onProgressUpdate().

but findViewById isn't accessible in AsyncTask.

If this is an inner class of your Activity then initialize the View in the Activity then update it in your task as described above.

If it is its own file then you will want to use an interface and have a callback to the Acitivty in onPostExecute(), onPreExecute(), or onProgressUpdate(). You can see an example of that in this SO answer.

I think I need to use setContentView to allow findViewById

Definitely! But as stated above, do this before the task such as in onCreate() of your Activity.

Edit

onProgressUpdate() takes a param but your onProgressUpdate() doesn't so it isn't the same method. That's why it complained when you had @Override which is the point of the annotation. It complains and you know you are suppose to be overriding a method so you know something is wrong with it.

Change it to

 protected void onProgressUpdate(Void...values) {
    statusMessage.setText("testing");
 }

onProgressUpdate() link

http://developer.android.com/reference/android/os/AsyncTask.html#onProgressUpdate(Progress...)

Community
  • 1
  • 1
codeMagic
  • 44,549
  • 13
  • 77
  • 93
  • I've updated the question with my recent changes. However, the text isn't change yet. am I missing a piece? – dcp3450 Jan 13 '14 at 19:28
  • 1
    Yes, I don't see `statusMessage` initialized anywhere. Anyway, you need to use the callback/interface method I linked to or make the `AsyncTask` an inner class of your splash `Acitivity`. – codeMagic Jan 13 '14 at 19:33
  • I initialized it in the onCreate of "baseActivity.java" that calls the AsyncTask in JSONParser.java. I tried initializing it JSONParser.java but that's where I ran into the issue. – dcp3450 Jan 13 '14 at 19:37
  • Yes, because your `AsyncTask` doesn't have access to it. Follow one of my two suggestions in my previous comment and you will be fine. Life will be grand again...I promise! – codeMagic Jan 13 '14 at 19:41
  • Seems like making it an inner class is hedging to be the best route. These calls aren't made anywhere else other than the splash screen. Keeping the AsyncTask in a different file was done mainly for easier upkeep later, that's all. – dcp3450 Jan 13 '14 at 20:06
  • @dcp3450 using interface is also a good choice. there is nothing difficult in implementing it – Raghunandan Jan 13 '14 at 20:12
  • If its not used anywhere else then I would just make it an inner class. But as Raghunandan said, implementing the `interface` is easy as well. But if you only use it in this class then either way is fine. – codeMagic Jan 13 '14 at 20:13
  • I've moved everything for the AsyncTask into "SplashScreen.java" and it works (the parsing function that is). statusMessage is initialized in the onCreate of SplashScreen and I have `statusMessage.setText("testing");` in `protected void onProgressUpdate(String... params)` but statusMessage doesn't change. thoughts? – dcp3450 Jan 13 '14 at 20:29
  • Yes, just a second, I see the problem... – codeMagic Jan 13 '14 at 20:32
  • Made the change (got the @Override error again so I removed it) and it didn't change the text. I did a `Log.d()` inside the `onProgressUpdate()` to do some debugging and it didn't run. Seems like the method isn't being called. – dcp3450 Jan 13 '14 at 21:04
  • According android docs I need `publishProgress` to be called in the doInBackground(). Correct? – dcp3450 Jan 13 '14 at 21:11
  • Yes you do. Sorry, I guess I just assumed you were doing that – codeMagic Jan 13 '14 at 21:13
  • Ok, I got to run using `publishProgress(params[3]);` params[3] is my update text passed by each method that calls the AsyncTask. I need to run each call one at a time, otherwise they all run at once. Is there a good practice to run the next function after an AsyncTas finishes. I can't place it directly in the onPostExecute since there are about 5 calls to make and I'm using one AsyncTask. – dcp3450 Jan 13 '14 at 22:03
  • I don't understand the last sentence. You can call a function from `onPostExecute()` or as many as you want. Either that or use the callback like I suggested earlier and linked to. – codeMagic Jan 13 '14 at 22:53
1

You should use onProgressUpdate, that method has acces to the ui thread.

public class yourAsync extends AsyncTask<> {

  @Override
  protected void onProgressUpdate() {
    textView.setText();
  }

}
1

put something like this in your activity

Handler statusUpdateHandeler = new Handler()........

In your thread, call the handler (send it a message)

MainActivity.statusUpdateHandler.sendEmptyMessage(1);

In you actual handler code, set the status message.

john
  • 11
  • 1
0
I think I need to use setContentView to allow findViewById to work but I'm not sure how.

Yes. You need to use setContentView(R.layout.activity_splash_screen) in onCreate.

You can initialize your view in onCreate make asynctask an inner class of activity and update ui in onPreExecute.

TextView statusMessage;
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_splash_screen);
    statusMessage = (TextView) findViewById(R.id.statusMessage);
}

Also you can use a progressdialog and display the message. I think using progressdialog would be a better choice than textview. You can publish progress in doInbackground and update progress dialog in onProgressUpdate()

http://developer.android.com/reference/android/os/AsyncTask.html

Raghunandan
  • 132,755
  • 26
  • 225
  • 256
  • I'm not calling the AsycnTask within the splash screen activity. I've updated/edited my question with more detail. – dcp3450 Jan 13 '14 at 19:31
  • @dcp3450 either make it an inner class or use interface a callback to the activity and update ui in activtiy – Raghunandan Jan 13 '14 at 19:32