Solution:
Okay,I've found the solution from your answers since your answers are not completely working
First we need to use Handler to post a Runnable to main/UI thread to run UpdateDisplay() and but define ProgressDialog under UIThread not other threads which was also crucial.
Here is the final code :
public final String RSSFEEDOFCHOICE = "http://www.deals2buy.com/rssgen/tech.xml";
public final String tag = "RSSReader";
private RSSFeed feed = null;
private Handler handler = new Handler();
private ProgressDialog dialog;
/** Called when the activity is first created. */
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
dialog = ProgressDialog.show(RSSReader.this, "Loading",
"Loading, please wait..");
Thread t = new Thread() {
public void run() {
feed = getFeed(RSSFEEDOFCHOICE);
handler.post(new Runnable() {
public void run() {
dialog.dismiss();
UpdateDisplay();
};
});
}
};
t.start();
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Problem :
When Android application first load, this is what happens :
Retrieving RSS content from Url and parse it into RSSFeed feed instance variable via getFeed(String url).
Showing these feeds to users in ListView via UpdateDisplay() method.
When these are happening, I wanted to show a ProgressDialog to users to notify them about system are retriving content like "Loading, please wait..." Once getFeed(String Url):RSSFeed is done, ProgressDialog will be dismissed and UpdateDisplay():void will be invoked.
So this is my first attempt :
public final String RSSFEEDOFCHOICE = "somewhere.xml"; //coming from http
public final String tag = "RSSReader";
private RSSFeed feed = null;
/** Called when the activity is first created. */
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
ProgressDialog dialog = ProgressDialog.show(RSSReader.this, "Loading...", "Loading, please wait");
feed = getFeed(RSSFEEDOFCHOICE);
dialog.dismiss();
UpdateDisplay();
}
And it doesn't show the ProgressDialog so it didn't work the way I want. Since I belived it is because ProgressDialog is continues progress, it should be handled by another Thread.
Here is my second attempt :
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
Thread t = new Thread()
{
public void run()
{
ProgressDialog dialog = ProgressDialog.show(RSSReader.this, "Loading...", "Loading, please wait");
feed = getFeed(RSSFEEDOFCHOICE);
dialog.dismiss();
}
};
UpdateDisplay();
}
It was okay till UpdateDisplay() since this method was handled by main thread and it wasn't waiting anything so I thought maybe I should have put it under t Thread after dialog.dismiss().
So I did this :
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
Thread t = new Thread()
{
public void run()
{
ProgressDialog dialog = ProgressDialog.show(RSSReader.this, "Loading...", "Loading, please wait");
feed = getFeed(RSSFEEDOFCHOICE);
dialog.dismiss();
UpdateDisplay();
}
};
}
But then debugger said at run-time : only the main thread which handles onCreate():void can reach and use View objects because it creates them.
Now, I am so messed up and feel like quitting programming.
Some one can help me :/
Thanks in advance.
You could use AsyncTask, thats exactly what its for. Since onPostExecute(Long result) is done on the UI thread, it wont crash when looking for View objects.
Here is a example taken from the asyncTask reference
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
}
return totalSize;
}
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
}
What you want to do is obtain the RSS feed in doInBackground(), and then update the UI in onPostExecute.
In your onCreate() method, invoke the asyncTask.
new DownloadFilesTask().execute(url1, url2, url3);
Okay,I've found the solution from your answers since your answers are not completely working
First we need to use Handler to post a Runnable to main/UI thread to run UpdateDisplay() and but define ProgressDialog under UIThread not other threads which was also crucial.
Here is the final code :
public final String RSSFEEDOFCHOICE = "http://www.deals2buy.com/rssgen/tech.xml";
public final String tag = "RSSReader";
private RSSFeed feed = null;
private Handler handler = new Handler();
private ProgressDialog dialog;
/** Called when the activity is first created. */
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
dialog = ProgressDialog.show(RSSReader.this, "Loading",
"Loading, please wait..");
Thread t = new Thread() {
public void run() {
feed = getFeed(RSSFEEDOFCHOICE);
handler.post(new Runnable() {
public void run() {
dialog.dismiss();
UpdateDisplay();
};
});
}
};
t.start();
}
You have to run your request in another thread than the progressdialog. So try with
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
ProgressDialog dialog = ProgressDialog.show(RSSReader.this, "Loading...", "Loading, please wait");
Thread t = new Thread()
{
public void run()
{
feed = getFeed(RSSFEEDOFCHOICE);
dialog.dismiss();
UpdateDisplay();
}
};
}
And depending on what you do in update display you should run it in the UI thread.
Actually the best way would be to use AsyncTask.
However as a quick workaround you could do smth like this:
private Handler handler = new Handler();
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
Thread t = new Thread()
{
public void run()
{
ProgressDialog dialog = ProgressDialog.show(RSSReader.this, "Loading...", "Loading, please wait");
feed = getFeed(RSSFEEDOFCHOICE);
dialog.dismiss();
handler.post(new Runnable() {
public void run() {
UpdateDisplay();
}
});
}
};
}
Related
I have this class that gets called from a fragment. On progress update gets called but the message will not update. I also am not seeing any progress bar or spinner. Just the title and the message, seen some similar problems but nothing where the progress bar isn't showing at all. Also, my message will not update at all in onProgressUpdate but printing out the values does show that it increments inside of the onProgressUpdate.
Edit: Here is how I start the task
DownloadFilesTask download = new DownloadFilesTask();
download.execute(urls.toArray(new String[urls.size()]));
Here is the class
private class DownloadFilesTask extends AsyncTask<String, Integer, Long> {
ProgressDialog progressDialog;
#Override
protected void onPreExecute()
{
progressDialog = ProgressDialog.show(getActivity(), "Downloading","Downloaded 0/"+urls.size(), false);
progressDialog.setProgress(0);
progressDialog.setMax(urls.size());
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
}
#Override
protected Long doInBackground(String[] urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
//Do things in background here
publishProgress(new Integer[] {i});
}
return totalSize;
}
#Override
protected void onProgressUpdate(final Integer... progress) {
System.out.println(progress[0]); //This does print correctly
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
progressDialog.setProgress(progress[0]);
progressDialog.setMessage("Downloaded "+ progress[0] +"/"+urls.size());
}
});
}
#Override
protected void onPostExecute(Long result) {
progressDialog.dismiss();
Toast t = Toast.makeText(getActivity(), "Downloaded", Toast.LENGTH_LONG);
t.show();
}
}
The issue is with the way your ProgressDialog is initialized.
Replace your onPreExecute with this:
#Override
protected void onPreExecute() {
progressDialog = new ProgressDialog(activity);
progressDialog.setTitle("Downloading");
progressDialog.setMessage("Downloaded 0/" + urls.size());
progressDialog.setIndeterminate(false);
progressDialog.setProgress(0);
progressDialog.setMax(urls.size());
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.show();
}
Essentially, you need to call setProgressStyle before calling show.
Additionally, you can remove the runOnUiThread code in onProgressUpdate because onProgressUpdate is invoked on the UI thread.
Not sure of the exact cause, but it is not required to setProgress on runnable as onProgressUpdate will run on UI thread.
Try Replacing
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
progressDialog.setProgress(progress[0]);
progressDialog.setMessage("Downloaded "+ progress[0] +"/"+urls.size());
}
});
with
progressDialog.setProgress(progress[0]);
progressDialog.setMessage("Downloaded "+ progress[0] +"/"+urls.size());
Also - Are you doing networking stuff in doInbackground(), else we cannot see progress which will be dismissed on onPostExecute().
I am new to android programming. I am developing a web crawler for which i am using a Async Task and it is working well.In order to keep user informed,i am using progress dialog. My problem is,if i use a Progress Dialog my program takes more time to execute and when i won`t use the progress dialog,it executes faster.
Done Work
OnCreate Method
protected void onCreate(Bundle savedInstanceState) {
try {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_results);
Intent intent = getIntent();
s1 = intent.getStringExtra("Number1");
s2 = intent.getStringExtra("Number2");
s3=intent.getIntExtra("selectedItem",0);
HttpAsyncTask asyncTask = new HttpAsyncTask();
asyncTask.execute();
}catch (Exception e)
{
messageBox("Exception",e.getMessage());
}
}
Async Task Class
private class HttpAsyncTask extends AsyncTask<List<String>, Integer, List<String>> {
private ProgressDialog dialog;
#Override
protected void onPreExecute()
{
dialog = new ProgressDialog(Results.this);
dialog.setIndeterminate(true);
dialog.setMessage("Please Wait");
dialog.setCancelable(true);
dialog.show();
super.onPreExecute();
}
#Override
protected List<String> doInBackground(List<String>... urls) {
//android.os.Debug.waitForDebugger();
// spinner.setVisibility(View.VISIBLE);
List<String>resultList=new ArrayList<String>();
try
{
if(isCancelled())
return resultList;
resultList=WebCrawlerClass.GetPost(s1,s2,s3);
}catch (Exception e)
{
messageBoxs("Error", e.getMessage());
}
return resultList;
}
// onPostExecute displays the results of the AsyncTask.
#Override
protected void onPostExecute(List<String> result)
{
if(dialog.isShowing())
{
dialog.dismiss();
}
if(s3 == 2)
{
docListAdapter=new ListViewData(Results.this,result);
}
else {
docListAdapter = new NameNumListData(Results.this, result);
}
docList=(ListView)findViewById(R.id.listView2);
docList.setAdapter(docListAdapter);
super.onPostExecute(result);
}
#Override
protected void onCancelled() {
super.onCancelled();
this.cancel(true);
}
}
Am I missing something? Need help..
Thanks and Regards,
Abhinav
In you activity
// Start the progress dialog
..
Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
// dismiss the progress dialog
}
};
HttpAsyncTask asyncTask = new HttpAsyncTask(handler);
asyncTask.execute();
In your asynctask class
private class HttpAsyncTask extends AsyncTask<List<String>, Integer, List<String>> {
private Handler handler = null;
public HttpAsyncTask (Handler handler) {
this.handler = handler;
}
protected Void doInBackground(Void... params) {
//Perform your task
// When you know that task is finished , fire following code
if (null != handler) {
Message message = handler.obtainMessage();
message.obj = Any data you want to sent to the activity
message.what = 1 ; ( Optional )
handler.sendMessage(message);
}
}
Thus when sendMessage function is called from doInbackground.. your handleMessage in your activity will get triggered and then you should dismiss the progress dialog
Hope this will improve the performance issue what you are facing
Remove super.onPreExecute(); in onPreExecute() method and check .It might Help
I am trying to put a progressDialog in my fragment so my app feels smoother between each actions. The problem that I have is that the main thread is returning the view before the async thread has modified it. I was doing a Thread.join() before switching to this methode.
public class MyFragment extends Fragment {
public View onCreateView(LayoutInflater inflater,ViewGroup container, Bundle args) {
mLLayout = new LinearLayout(getActivity());
mLLayout.setPadding(0, 0, 0, 0);
mLLayout.setOrientation(LinearLayout.VERTICAL);
mScroll = new ScrollView(getActivity().getApplicationContext());
mScroll.setVerticalScrollBarEnabled(true);
mScroll.addView(mLLayout);
new AsyncCaller().execute();
return mScroll;
}
private class AsyncCaller extends AsyncTask<Void, Void, Void>
{
ProgressDialog nDialog = new ProgressDialog(getActivity());
#Override
protected void onPreExecute()
{
super.onPreExecute();
//this method will be running on UI thread
nDialog = new ProgressDialog(getActivity());
nDialog.setMessage("Loading..");
nDialog.setTitle("Checking Network");
nDialog.setIndeterminate(false);
nDialog.setCancelable(true);
nDialog.show();
}
#Override
protected Void doInBackground(Void... params)
{
//Doing http requests and modifying views
return null;
}
#Override
protected void onPostExecute(Void result)
{
super.onPostExecute(result);
//this method will be running on UI thread
nDialog.dismiss();
}
}
...
}
I cant find a solution without blocking the main thread and by the same way not seeing the progressDialog at all and having a big lag instead. Also, I never saw my code go into "onPostExecute()".
Thanks in advance for your help!
Striaght from an app i've done, this code should help:
ProgressBar mProgress = (ProgressBar) findViewById(R.id.progressBar);
private float mProgressStatus = 0;
private Handler mHandler = new Handler();
private void startProgressBar()
{
new Thread(new Runnable()
{
#Override
public void run()
{
while (mProgressStatus < 100)
{
try
{
Thread.sleep(1000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
mProgressStatus += 1.3;
mHandler.post(new Runnable()
{
#Override
public void run()
{
mProgress.setProgress((int) mProgressStatus);
}
});
}
}
}).start();
}
I am trying to make a progress dialog that pop up while things are loading. I have figured out how to make dialog boxes appear and disappear and can change whats in them but I have multiple async tasks and want the dialog to appear when the first async task starts and then disappear when the last async tasks finishes.
Is there a way for the dialogs to know when all async tasks are complete for a given activity? I am having problems on how to approach this issue. Thanks for the help!
Here is a exact sample code which i used to acheive the same functionality.
public class LoginActivity extends Activity
{
public static String TAG = "Login_Activity: ";
private EditText usernameEditText;
private EditText passwordEditText;
private ProgressDialog progress_dialog;
private int taskCount = 0;
private void updateTaskCount(int value)
{
taskCount += value;
if(progress_dialog != null && taskCount == 0)
{
progress_dialog.dismiss();
}
}
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
usernameEditText = (EditText) findViewById(R.id.login_username);
passwordEditText = (EditText) findViewById(R.id.login_password);
progress_dialog = new ProgressDialog(this);
}
public void LoginClick(View view)
{
String URL = "http://SOME.com/api/Members?Username=" +
usernameEditText.getText().toString()+ "&Password=" +
passwordEditText.getText().toString();
progress_dialog.setMessage("Authenticating. Please wait...");
progress_dialog.setCancelable(false);
progress_dialog.show();
new AuthenticateUserFromServer().execute(URL);
updateTaskCount(1);
new NotifyWebService ().execute("some other url");
updateTaskCount(1);
}
protected void onDestroy()
{
progress_dialog.dismiss();
super.onDestroy();
}
#Override
protected void onPause()
{
progress_dialog.dismiss();
super.onPause();
}
private class AuthenticateUserFromServer extends AsyncTask <String, Void, String>
{
protected String doInBackground(String... urls)
{
return Utility.readJSONFromWebService(urls[0]);
}
protected void onPostExecute(String result)
{
// do other stuff
updateTaskCount(-1);
}
}
private class NotifyWebService extends AsyncTask <String, Void, String>
{
protected String doInBackground(String... urls)
{
return Utility.readJSONFromWebService(urls[0]);
}
protected void onPostExecute(String result)
{
// do other stuff
updateTaskCount(-1);
}
}
}
If you have multiple/separate classes for async tasks you can create a static utility class to keep track of and update count.
I have a splashscreen which lasts 5 seconds, and I want to represent the progress using a ProgressBar.
public class SplashActivity extends Activity {
private static final long SPLASHTIME = 5000;
private ProgressBar progressBar;
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.splash);
SplashHandler handlerSplash = new SplashHandler();
progressBar = (ProgressBar) findViewById(R.id.progression);
progressBar.setMax((int) ((SPLASHTIME) / 1000));
progressBar.setProgress(0);
Message msg = new Message();
msg.what = 0;
handlerSplash.sendMessageDelayed(msg, SPLASHTIME);
ThreadProgressBar threadProgress = new ThreadProgressBar();
threadProgress.start();
}
private class ThreadProgressBar extends Thread {
ProgressBarHandler handlerProgress = new ProgressBarHandler();
public void run() {
try {
while (progressBar.getProgress() <= progressBar.getMax()) {
Thread.sleep(1000);
handlerProgress.sendMessage(handlerProgress.obtainMessage());
}
} catch (java.lang.InterruptedException e) {
}
}
}
private class ProgressBarHandler extends Handler {
public void handleMessage(Message msg) {
progressBar
.incrementProgressBy((int) (SPLASHTIME / SPLASHTIME));
}
}
private class SplashHandler extends Handler {
public void handleMessage(Message msg) {
switch (msg.what) {
default:
case 0:
super.handleMessage(msg);
// new ProgressBarIncrease().execute();
Intent intent = new Intent();
intent.setClass(SplashActivity.this, RdvTab.class);
startActivity(intent);
}
}
}
I guess since SplashActivity itself is an activity, it is ok to block UI right? AsyncTask sometimes run not gradually, if you want the update to be displayed smoothly, how about changing to worker Thread and Handlder.
Create Handler inside SplashActivity
In the main Thread, display progressBar or splash or whatever you like
While make another Thread to run the countdown, once in every second sendEmptyMessage() to Handler. After 5 seconds, send a message to Handler to dismiss dialog and splash then the worker Thread ends.
UPDATED: Sorry for the slow feedback. How about this? I haven't tested it yet and it's not the best implementation though, you can use this logic
public class SplashActivity extends Activity {
private static final int SPLASHTIME = 5000;
// u can change the value here for smoother effect
private static final long UPDATEINTERVAL = 1000;
private ProgressBar progressBar;
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.splash);
progressBar = (ProgressBar) findViewById(R.id.progression);
new Thread(new Runnable(){
#Override
public void run(){
int progress = 0;
while(true){
// send current progress to handler
mHandler.sendEmptyMessage(progress);
// break from the loop after SPLASHSCREEN millis
if(progress > SPLASHSCREEN)
break;
// increase the progress
progress = (int) (progress + UPDATEINTERVAL);
// sleep the worker thread
Thread.sleep(UPDATEINTERVAL);
}
}
}).start();
}
private Handler mHandler = new Handler(){
#Override
public void handleMessage(Message message){
// get the current progress
int progress = message.what;
if(progress <= SPLASHTIME){
progressBar.setProgress(progress);
}
else{
// finish splashActivity here & do what u want do to after splashscreen, for example
finish();
Intent intent = new Intent(SpashActivity.this, MenuActivity.class);
startActivity(intent);
}
}
}
}
You should divide the splash screen time into equal amounts and send the progress update at those intervals.
For example:Lets say the total time is divided into 50 equal intervals as follows
protected void onPreExecute() {
progressbarStep = progressbarWidth/50;
timeStep = 5000/50;
progress = 0;
}
#Override
protected Void doInBackground(Void... params) {
try {
while(progress < progressbarWidth){
progress += progressbarStep;
publishProgress(progress);
SystemClock.sleep(timeStep);
}
return null;
} catch (Exception e) {
}
return null;
}
#Override
protected void onProgressUpdate(Integer... values) {
progressBar.setProgress(values[0]);
}