Android. ProgressBar doesn't work? - android

I loading some data from a database and I'd like to display a circle animation during this, because it's take time. The circle appears but only after loadContent() which load data.
The code:
final String PREFS_NAME = "MyPrefsFile";
SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
ProgressBar p = (ProgressBar) findViewById(R.id.imgProgress);
p.setEnabled(true);
if (settings.getBoolean("my_first_time", true)) {
// the app is being launched for first time, do something
Log.d("Launched:", "first time");
loadContent();
// record the fact that the app has been started at least once
settings.edit().putBoolean("my_first_time", false).commit();
}
p.setEnabled(false);
In XML:
<ProgressBar
android:id="#+id/imgProgress"
style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_centerInParent="true"
android:layout_height="wrap_content" />

Why not just do this ?
public class SomeTask extends AsyncTask<Void, String, Void>{
ProgressDialog dialogue;
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
dialogue.dismiss();
//If Using some adapter; someadapteradapter.notifyDataSetChanged();
}
#Override
protected void onPreExecute() {
dialogue = new ProgressDialog(ProgressBar.this);
dialogue.setTitle("Loading items..");
dialogue.show();
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... params) {
//Your task!!
return null;
}
}
What can be more simple than this..:)

I don't know what is loadContent method but I'd suggest you to do an AsyncTask (if it's not the case). You will be able to show/hide your ProgressBar as follows:
// loadContent method
public class loadContent extends AsyncTask<String, Void, String> {
#Override
protected void onPreExecute() {
// set your progress bar to visible
((ProgressBar) findViewById(R.id.imgProgress)).setVisibility(View.VISIBLE);
}
#Override
protected String doInBackground(String... params) {
// do some stuff: load datas from sql, load images.. whatever
// and return a string value for onPostExecute (string = "Loaded"
return string;
}
#Override
protected void onPostExecute(String result) {
if(result.equals("Loaded") {
// the loading is finish, display your datas
// set your progress bar to gone
((ProgressBar) findViewById(R.id.imgProgress)).setVisibility(View.GONE);
}
}
}
Here and here, you will see a good example of an AsyncTask method. Then, you just have to add the visibility attribute to your view as:
<ProgressBar
android:id="#+id/imgProgress"
style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_centerInParent="true"
android:layout_height="wrap_content"
android:indeterminate="true"
android:visibility="gone" />
Hope this helps.

Related

activity to fragment method calling in a thread with progressbar

I am using this code, everything are working fine, but progressbar is not showing. I want to block my ui during the method implementation and want to show progressbar. I want to get behaviour like progressDialog.
Here is my method
public void effct(int effectNo) {
final int finalEffectNO = effectNo;
getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
progressLayout.setVisibility(View.VISIBLE);
progressLayoutLinear.setVisibility(View.VISIBLE);
Thread thread = new Thread(){
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
imageViewFragment.applyEffect(finalEffectNO);
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
progressLayout.setVisibility(View.GONE);
progressLayoutLinear.setVisibility(View.GONE);
}
});
}
};
thread.start();
}
My xml code for progressLayout
<LinearLayout
android:id="#+id/progressBarLinearLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#color/colorPrimaryDark"
android:gravity="center"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
android:padding="12dp"
android:visibility="gone"
android:orientation="horizontal">
<ProgressBar
android:id="#+id/progressBar"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginRight="10dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Loading"
android:textColor="#FFFFFF"
android:textStyle="bold"
android:textSize="18sp"/>
</LinearLayout>
For above your requirement you must use ProgressDialog for same, here is an example
Example
Try using an AsyncTask instead of Thread, something like this :
new AsyncTask<Void, Void, Void>() {
#Override
protected void onPreExecute() {
progressLayoutLinear.setVisibility(View.VISIBLE);
}
#Override
protected Void doInBackground(final Void ... params ) {
runOnUiThread(new Runnable() {
#Override
public void run() {
imageViewFragment.applyEffect(finalEffectNO);
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
}
});
return null;
}
#Override
protected void onPostExecute( final Void result ) {
progressLayoutLinear.setVisibility(View.GONE);
}
}.execute();
Hope this helps
There’s a few ways to solve your problem - check this video for more information. The most basic approach might be an AsyncTask, which could look like this:
public class DummyAsyncTask extends AsyncTask<Void, Void, Void> {
private final Window window;
private final ProgressBar progressBar;
public DummyAsyncTask(Window window, ProgressBar progressBar) {
this.window = window;
this.progressBar = progressBar;
}
#Override protected void onPreExecute() {
window.setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
progressBar.setVisibility(View.VISIBLE);
}
#Override protected Void doInBackground(Void... voids) {
// Do the heavy lifting.
}
#Override protected void onPostExecute(Void aVoid) {
window.clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
progressBar.setVisibility(View.GONE);
}
}
You execute it by running new DummyAsyncTask(/* params */).execute();.
Do note that AsyncTask does not adhere to the lifecycle and holding a reference to a Context aware instance is just asking for trouble. A safer alternative might be using LiveData:
public void effect(int effectNo) {
// Show progress and disable user interaction here.
final ListData<Content> data = model.applyEffect(effectNo);
data.observe(this, (Observer<Content>) c -> {
// Apply results, hide progress & enable user interaction.
});
}
Given the above, you should be careful how you handle showing & hiding progress, so you don’t accidentally disable user interaction forever.

ProgressBar Spinner for Async Task doesn't work

My problem is that when i click button "Click" to call my API it should show my progressBar(spinner) while I'm calling API. Instead my application freeze for less than a second and then when it's done calling it shows my loading spinner for a brief time (it just flash)
Here is my code
private ProgressBar spinner;
public View onCreateView(...)
{
spinner = (ProgressBar) view.findViewById(R.id.progressBar1);
spinner.setVisibility(View.GONE);
...
}
private class MyTask extends AsyncTask<String, Void, Void> {
String pageContent = "";
DataOutputStream wr;
#Override
protected void onPreExecute() {
spinner.setVisibility(View.VISIBLE);
}
#Override
public Void doInBackground(String... params) {
requestResult.setSuccess(false);
HttpURLConnection connection;
try {
String url = "myURL";
//I only call my Api here. I delete rest so this won't bother you
requestResult.setSuccess(true);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
JsonParser parser = new JsonParser();
//Same here i delete nonimportant
MyResponse = new Gson().fromJson(jsonContent, MyResponse.class);
done();
spinner.setVisibility(View.GONE);
}
}
I've tried hounder different things it always freeze for a second and then my loading spinner flash and my content from API is shown.
Can you help me with that one, please?
My xml file
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/scroll_view_send"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<RelativeLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:minWidth="25px"
android:minHeight="25px">
<ProgressBar
android:id="#+id/progressBar1"
style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_below="#id/buttonSend"
android:visibility="gone"/>
</RelativeLayout>
</ScrollView>
Try the below snippet. It does not require spinner to be declared in layout file.
AsyncTask<String, String, String> asyncObject =
new AsyncTask<String, String, String>() {
ProgressDialog progDailog;
#Override
protected void onPreExecute() {
super.onPreExecute();
progDailog =
new ProgressDialog(Activity.this);
progDailog.setMessage("Loading");
progDailog.setCancelable(false);
progDailog.show();
}
#Override
protected String doInBackground(String... urls) {
//Do background stuff here
return null;
}
#Override
protected void onPostExecute(String result) {
progDailog.cancel();
//Do post background stuff here.
}
};
asyncObject.execute(null, null, null);
Please try this working sample, pass the spinner to your MyTask like this:
private class MyTask extends AsyncTask<String, Void, Void> {
String pageContent = "";
DataOutputStream wr;
private final ProgressBar progress;
public MyTask(final ProgressBar progress) {
this.progress = progress;
}
#Override
protected void onPreExecute() {
progress.setVisibility(View.VISIBLE);
}
...
#Override
protected void onPostExecute(Void result) {
JsonParser parser = new JsonParser();
//Same here i delete nonimportant
MyResponse = new Gson().fromJson(jsonContent, MyResponse.class);
done();
progress.setVisibility(View.GONE);
}
}
Then call new MyTask(progress).execute();
EDIT: In your question you refer that your phone is freezing while calling the MyTask...
Please check this step to avoid freezing your UI in AsyncTask:
Do not call MyTask using new MyTask().get()
Try moving to doInBackground this part MyResponse = new Gson().fromJson(jsonContent, MyResponse.class); done(); this could be expensive.
Hope its helps!!

Activity not starting

I can get the progress dialog to stop, but the TabbedView activity never starts, just goes to a black screen. Any ideas?
class DownloadWebPageTask extends AsyncTask<String, Void, String> {
private final ProgressDialog dialog = new ProgressDialog(MainScreen.this);
#Override
protected void onPreExecute() {
dialog.setMessage("Gathering data for\n"+selectedSportName+".\nPlease wait...");
dialog.show();
}
#Override
protected String doInBackground(String... urls) {
String response = "";
updateMaps();
return response;
}
#Override
protected void onPostExecute(String result) {
dialog.dismiss();
startTabbedViewActivity();
}
}
private void startTabbedViewActivity(){
Intent intent = new Intent(this, TabbedView.class);
intent.putExtra(SPORT_NAME_EXTRA, selectedSportName);
intent.putExtra(HEADLINES_FOR_SPORT_EXTRA, existingSportHeadlines.get(selectedSportName));
intent.putExtra(SCORES_FOR_SPORT_EXTRA, existingSportScores.get(selectedSportName));
intent.putExtra(SCHEDULE_FOR_SPORT_EXTRA, existingSportSchedule.get(selectedSportName));
startActivity(intent);
}
I have looked over the Manifest file, and I'm not seeing anything weird looking. Can't figure this one out.
Is the layout of the activity orientated correctly
android:orientation="vertical"
You forgot to add #Override above 'onPostExecute' method so it is not executed at all.

Show ProgressBar in another thread

For a few days a have some problem.
I need to show simple ProgressBar (not dialog) while doing some stuff in main thread...
I thought its a very simple question, but i cant do this, help me please.
First i tried simple setVisibility(View.VISIBLE) before and setVisibility(View.GONE) after.
But this is doing in the same thread, and ProgressBar freezed while my function working.
Now i have this code, but i have some error, and i dont know whats wrong..
my simple layout :
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<ProgressBar
android:id="#+id/loading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="gone" />
</FrameLayout>
i have a base activity :
public class BaseActivity extends Activity {
public ProgressBar loading;
public class ProgressBarShow extends AsyncTask<Void, Void, Void> {
protected Void doInBackground(Void... unused) {
return(null);
}
protected void onProgressUpdate() {
}
protected void onPreExecute() {
loading.setVisibility(View.VISIBLE);
}
protected void onPostExecute() {
}
}
}
and finally my working activity , which extends BaseActivity
public class SearchActivity extends BaseActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
loading = (ProgressBar) findViewById(R.id.loading);
new ProgressBarShow().execute();
//doing long stuff
//new ProgressBarHide().execute(); there isnt, but sense the same
}
}
I have many activities, which need progress bar, thats why i have created BaseActivity,
to not to dublicate code.
I need to do long work (stuff function) in main thread, because i want to freeze main window and not to allow user do anything (click button etc..), just show working ProgressBar.
Whats wrong in my example? Or give me some advice how can i do this better
class ProgressTask extends AsyncTask<Integer, Integer, Void>{
ProgressBar progress;
Context context;
public ProgressTask(ProgressBar progress, Context context) {
this.progress = progress;
this.context = context;
}
#Override
protected void onPreExecute() {
// initialize the progress bar
// set maximum progress to 100.
progress.setMax(100);
}
#Override
protected Void doInBackground(Integer... params) {
// get the initial starting value
int start=params[0];
// increment the progress
for(int i=start;i<=100;i+=5){
try {
boolean cancelled=isCancelled();
//if async task is not cancelled, update the progress
if(!cancelled){
publishProgress(i);
SystemClock.sleep(1000);
}
} catch (Exception e) {
Log.e("Error", e.toString());
}
}
return null;
}
//Has direct connection to UI Main thread
//Called everytime publishProgress(int) is called in doInBackground
#Override
protected void onProgressUpdate(Integer... values) {
progress.setProgress(values[0]);
Toast.makeText(context, "test"+values[0], Toast.LENGTH_SHORT).show();
}
#Override
protected void onPostExecute(Void result) {
// async task finished
Log.v("Progress", "Finished");
}
#Override
protected void onCancelled() {
progress.setMax(0);
}
}
Use AsyncTask http://developer.android.com/guide/topics/fundamentals/processes-and-threads.html Put your ProgressBar in it, while all work is doing in main thread

Updating TextView from Async Task which use custom program dialog

In one of my app, I have a scenario where I need to do some background task. For doing that I am using Async Task. Also I am using custom progress dialog. Below is the layout of the custom progress dialog
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/layout_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_vertical|center_horizontal"
android:orientation="vertical" >
<ProgressBar
android:layout_width="60dp"
android:layout_height="60dp"
android:indeterminateDrawable="#drawable/progressloader"
android:layout_gravity="center"/>
<TextView
android:id="#+id/progressMessage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#color/black"
android:textSize="18sp"
android:text="Please wait...." />
</LinearLayout>
Everything works fine but when I try to set text to TextView then I am getting java NullPointerException.
AsyncTask code
private class InitialSetup extends AsyncTask<String, Integer, Long> {
ProgressDialog dialog = new ProgressDialog(getParent(),R.style.progressdialog);
#Override
protected void onPreExecute() {
dialog.show();
dialog.setContentView(R.layout.progressbar);
}
#Override
protected Long doInBackground(String... urls) {
// txtView.setText("Testing"); here I am getting the error
fetchDetails();
return 0;
}
#Override
protected void onPostExecute(Long result) {
if (this.dialog.isShowing()) {
this.dialog.dismiss();
}
populateUI(getApplicationContext());
}
}
MainActivity
public class SummaryActivity extends Activity {
final TextView txtView = (TextView)findbyid(R.id.progressMessage);
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.accountsummary);
new InitialSetup().execute("");
}
}
If I understand correctly, your TextView of which you want to set the text can be found in the xml file progressbar.xml (i.e. R.layout.progressbar). This TextView can be obtained once the content view has been set (using setContentView()). In your code you set it before this call is been and the code of mussharapp, he is calling it to early. Namely, he calls it after the setContentView(R.layout.accountsummary) call which does not contain the TextView. Consequently, the variable txtView will be NULL and you will get a NullPointerException.
What you should do is the following:
Set the variable txtView in onPreExecute, after setContentView is called.
Based on Paresh Mayani's explanation: Use the runOnUiThread method.
For the code look down below:
private class InitialSetup extends AsyncTask<String, Integer, Long> {
ProgressDialog dialog = new ProgressDialog(getParent(),R.style.progressdialog);
// The variable is moved here, we only need it here while displaying the
// progress dialog.
TextView txtView;
#Override
protected void onPreExecute() {
dialog.show();
dialog.setContentView(R.layout.progressbar);
// Set the variable txtView here, after setContentView on the dialog
// has been called! use dialog.findViewById().
txtView = dialog.findViewById(R.id.progressMessage);
}
#Override
protected Long doInBackground(String... urls) {
// Already suggested by Paresh Mayani:
// Use the runOnUiThread method.
// See his explanation.
runOnUiThread(new Runnable() {
#Override
public void run() {
txtView.setText("Testing");
}
});
fetchDetails();
return 0;
}
#Override
protected void onPostExecute(Long result) {
if (this.dialog.isShowing()) {
this.dialog.dismiss();
}
populateUI(getApplicationContext());
}
}
Yes, because you are trying to set the TextView inside the doInBackground() method, and this is not allowed,
Why not allowed? Because There is a only one Thread running which is UI Main Thread, and it doesn't allowed to update UI from thread process. read more info here: Painless Threading
So there is a solution if you want to set the TextView inside the doInBackground() method, do the UI updating operations inside the runOnUiThread method.
Otherwise, suggestion is to do all the UI display/update related operations inside the onPostExecute() method instead of doInBackground() method of your AsyncTask class.
(TextView)findViewByid(R.id.progressMessage);
should only be executed after the command setContentView().
TextView txtView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.accountsummary);
**txtView = (TextView)findbyid(R.id.progressMessage);**
new InitialSetup().execute("");
}
Also you can only change UI elements in the main UI thread. doInBackground() is not in the main UI thread. Make UI changes in onPostExecute
public class InitialSetup extends AsyncTask<String, Integer, Long> {
private Activity activity;
ProgressDialog progressDialog;
public InitialSetup(Activity activity) {
this.activity = activity;
}
#Override
protected void onPreExecute() {
progressDialog = new ProgressDialog(activity);
progressDialog.setMessage("Starting task....");
progressDialog.show();
}
#Override
protected Long doInBackground(String... urls) {
// do something
//
return 0;
}
#Override
protected void onPostExecute(Long result) {
progressDialog.dismiss();
//Perform all UI changes here
**textView.setText("Text#2");**
}
}
The explanations are correct: You are not to make UI changes in any thread except the thread which create the UI. But AsyncTask has a method called
onProgressUpdate()
which always will run in the UI Thread. So based on the modifications by dennisg your code should look like this:
private class InitialSetup extends AsyncTask<String, String, Long> {
ProgressDialog dialog = new ProgressDialog(getParent(),R.style.progressdialog);
// The variable is moved here, we only need it here while displaying the
// progress dialog.
TextView txtView;
#Override
protected void onPreExecute() {
dialog.show();
dialog.setContentView(R.layout.progressbar);
// Set the variable txtView here, after setContentView on the dialog
// has been called! use dialog.findViewById().
txtView = dialog.findViewById(R.id.progressMessage);
}
#Override
protected Long doInBackground(String... urls) {
publishProgress("Testing");
fetchDetails();
return 0;
}
#Override
protected void onPostExecute(Long result) {
if (this.dialog.isShowing()) {
this.dialog.dismiss();
}
populateUI(getApplicationContext());
}
#Override
protected void onProgressUpdate(String... update) {
if (update.length > 0)
txtView.setText(update[0]);
}
}
Note that the type of the parameter of onProgressUpdate is the second type given in AsyncTask!
Extra: To make your code more robust you should check if the progress dialog still exists before setting the text.

Categories

Resources