I'm currently learning Android app development by working through a book and I'm currently struggling with something that seems to be fairly simple on the face of it. The interface consists of a button and a text view. The idea of the exercise is to demonstrate how using a separate thread is useful when performing time consuming tasks.
I've tried debugging and the values
array of the onProgressUpdate
method does contain the value passed into it and the crash seems to always happen when trying to set the text for myTextView
. I'd be grateful for any help.
Code:
package com.ebookfrenzy.asyncdemo;
import androidx.appcompat.app.AppCompatActivity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private TextView myTextView;
private String tag = "Test";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void buttonClick(View view) {
AsyncTask task = new MyTask().execute();
}
private class MyTask extends AsyncTask<String,Integer,String> {
@Override
protected void onPreExecute() {
}
@Override
protected void onProgressUpdate(Integer... values) {
Log.i(tag,"publish: " + Integer.toString(values[0]));
myTextView.setText("Counter = " + values[0]);
}
@Override
protected void onPostExecute(String result) {
myTextView.setText(result);
}
@Override
protected String doInBackground(String... strings) {
int i = 0;
while (i <= 20) {
Log.i(tag,"before publish: " + Integer.toString(i));
publishProgress(i);
try {
Thread.sleep(1000);
i++;
} catch(Exception e) {
}
}
return "Button Pressed";
}
}
}
The Logcat output (created by the Log.i items added by me for troubleshooting) is usually the below but if the warning message that advises the app keeps crashing pops up the "before publish" item keeps populating with i incrementing each time until I close the warning message:
2020-12-13 23:17:04.499 31729-31772/com.ebookfrenzy.asyncdemo I/Test: before publish: 0
2020-12-13 23:17:04.503 31729-31729/com.ebookfrenzy.asyncdemo I/Test: publish: 0
The error section of the Logcat:
--------- beginning of crash
2020-12-13 23:19:47.635 353-353/com.ebookfrenzy.asyncdemo E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.ebookfrenzy.asyncdemo, PID: 353
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference
at com.ebookfrenzy.asyncdemo.MainActivity$MyTask.onProgressUpdate(MainActivity.java:34)
at com.ebookfrenzy.asyncdemo.MainActivity$MyTask.onProgressUpdate(MainActivity.java:25)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:715)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
2020-12-13 23:19:47.639 353-353/com.ebookfrenzy.asyncdemo I/Process: Sending signal. PID: 353 SIG: 9
I think myTextView
must be null.
Try this.
if (myTextView != null){
myTextView.setText("Counter = " + values[0]);
}
And you should initialize myTextView
at onCreate()
method.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myTextView = (TextView) findViewById(R.id.mytextviewid); // put
}