I am trying to learn and use ProgressBar in one of my projects. The ProgressBar itself works OK but when I try to show a toast once the ProgressBar has finished, my app crashes right at the time the toast message is supposed to show up. I have defined a "doOperation()" method to update the FileSize variable. Then I have set a while loop for the time that FileSize < 100 and it will trigger the doOperation method. I have also used an if statement to dismiss the ProgressBar once Filesize >= 100. The Toast is inside this if statement because I want it to show up right after the ProgressBar is dismissed. What am I doing wrong?
My code:
package com.example.togglebutton;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.Button;
import android.widget.ListView;
import android.widget.RatingBar;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ToggleButton;
import org.w3c.dom.Text;
import java.io.File;
public class MainActivity extends AppCompatActivity {
private Button btnprogress;
private ProgressDialog progressBar;
private int ProgressBarStatus = 0;
private Handler ProgressBarHandler = new Handler();
private int FileSize = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
addListenerButtonClick();
}
;
public void addListenerButtonClick() {
btnprogress = (Button) findViewById(R.id.button);
btnprogress.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
progressBar = new ProgressDialog(v.getContext());
progressBar.setCancelable(true);
progressBar.setMessage("File Downloading...");
progressBar.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressBar.setProgress(0);
progressBar.setMax(100);
ProgressBarStatus = 0;
FileSize = 0;
progressBar.show();
new Thread(new Runnable() {
@Override
public void run() {
while (ProgressBarStatus < 100) {
ProgressBarStatus = doOperation();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
ProgressBarHandler.post(new Runnable() {
@Override
public void run() {
progressBar.setProgress(ProgressBarStatus);
}
});
}
if (ProgressBarStatus >= 100) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
progressBar.dismiss();
Toast.makeText(MainActivity.this, "File Downloaded!", Toast.LENGTH_SHORT).show();
}
}
}).start();
}
});
}
public int doOperation() {
while (FileSize <= 10000) {
FileSize++;
if (FileSize == 1000) {
return 10;
} else if (FileSize == 2000) {
return 20;
} else if (FileSize == 3000) {
return 30;
}else if (FileSize == 4000) {
return 40;
}else if (FileSize == 5000) {
return 50;
}
else if (FileSize == 6000) {
return 60;
}
else if (FileSize == 7000) {
return 70;
}
else if (FileSize == 8000) {
return 80;
}
else if (FileSize == 9000) {
return 90;
}
else if (FileSize == 10000) {
return 100;
}
}
return 100;
};
}
Edit: My stacktrace of crash below :
2021-08-18 16:27:08.318 6281-6313/com.example.togglebutton E/AndroidRuntime: FATAL EXCEPTION: Thread-2
Process: com.example.togglebutton, PID: 6281
java.lang.NullPointerException: Can't toast on a thread that has not called Looper.prepare()
at com.android.internal.util.Preconditions.checkNotNull(Preconditions.java:157)
at android.widget.Toast.getLooper(Toast.java:179)
at android.widget.Toast.<init>(Toast.java:164)
at android.widget.Toast.makeText(Toast.java:492)
at android.widget.Toast.makeText(Toast.java:480)
at com.example.togglebutton.MainActivity$1$1.run(MainActivity.java:92)
at java.lang.Thread.run(Thread.java:923)
3
Answers
Finally fixed by adding below part inside my if statement where I had previously written the toast message:
try to put
progressBar.dismiss()
andToast.
methods also inProgressBarHandler.post(
as you do withprogressBar.setProgress
. These two methods are related to UI and probably must be called in UI thread alsoit would be easier to guess and help if you would post exception stacktrace…
One of the ways to arrive at the solution is to showing toast from UI thread.
Just call
showToast("FileDownloaded!");
instead of directly callingToast.makeText