ChrisBanes PullToRefresh 'Loading...' issue - android

I am using PullToRefresh ListView from chrisbanes which I found here.
I implemented it successfully, thanks to its documentations. :)
However, I am stuck at this one point now. I am using volley to get the data from the server. It works perfectly till I added a check to see if theres no more data then simply Toast the user.
I did like below,
#Override
public void onRefresh(
PullToRefreshBase<ListView> refreshView) {
if (hasMoreData()){
//Call service when pulled to refresh
orderService();
} else{
// Call onRefreshComplete when the list has been refreshed.
toastShort("No more data to load");
orderListAdapter.notifyDataSetChanged();
mPullRefreshListView.onRefreshComplete();
}
}
The toast comes up, but I also continue seeing the Loading... message below my ListView. I thought onRefreshComplete(); should take care of it but it didn't.
How do I do this? Please help.

After banging my head for almost 3hours I was able to solve this. It was quite simple tough.
What I did was created a Handler and a Runnable which calls mPullRefreshListView.onRefreshComplete(); and checked after some time that if mPullRefreshListView was still refreshing then call the method again which closes it on the next call. :)
Code goes like this..
#Override
public void onRefresh(PullToRefreshBase<ListView> refreshView) {
if (hasMoreData()) {
// Call service when pulled to refresh
toastShort("Last");
orderService();
} else {
// Call onRefreshComplete when the list has been
// refreshed.
toastShort("No more data to load");
upDatePull(); //this method does the trick
}
}
private void upDatePull() {
// lvOrders.setAdapter(null);
handler = new Handler();
handler.postDelayed(runnable, 1000);
}
Runnable runnable = new Runnable() {
#Override
public void run() {
mPullRefreshListView.onRefreshComplete();
if (mPullRefreshListView.isRefreshing()) {
Logger.d("xxx", "trying to hide refresh");
handler.postDelayed(this, 1000);
}
}
};
Credits to this link.

you should use onRefreshComplete(); in a separate thread like:
#Override
public void onRefresh(PullToRefreshBase<ListView> refreshView) {
if (hasMoreData()){
//Call service when pulled to refresh
orderService();
} else{
toastShort("No more data to load");
orderListAdapter.notifyDataSetChanged();
}
new GetDataTask(refreshView).execute();
}
public class GetDataTask extends AsyncTask<Void, Void, Void> {
PullToRefreshBase<?> mRefreshedView;
public GetDataTask(PullToRefreshBase<?> refreshedView) {
mRefreshedView = refreshedView;
}
#Override
protected Void doInBackground(Void... params) {
// Do whatever You want here
return null;
}
#Override
protected void onPostExecute(Void result) {
mRefreshedView.onRefreshComplete();
super.onPostExecute(result);
}
}

Related

Wait for activity to display

Currently I have a button that loads an activity.
That activity has a ListView in it that for whatever reason takes a fairly long time to load(not waiting for data, the data is already in memory). The problem is that while it's rendering the list, the UI is waiting where the button was clicked, and doesn't change screen until the list has fully loaded.
What I'd like, is to only display the list once the activity is loaded, so at least something happens as soon as they press the button(responsive UI is important).
Currently, my hack around solution to this, is to spawn a thread, wait for 50 milliseconds, and then set the adapter for my list(using runOnUiThread). Of course, if the activity takes longer than 50ms to load on some phones, then it'll have to load the entire list to load the activity again.
Current relevant code:
#Override
public void onPostResume() {
super.onPostResume();
new Thread(new Runnable() {
#Override
public void run() {
final AdapterData data = getData();
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
mActivity.runOnUiThread(new Runnable() {
#Override
public void run() {
myAdapter = new MyAdapter(MyActivity.this, data);
lvMyList.setAdapter(myAdapter);
}
});
}
}).start();
}
I just changed variable names in the code, but that's not relevant. This is just so you can see my general solution.
I feel like there should be some kind of callback that's called when the activity finishes creating. I thought that onPostResume waited for the activity to finish loading, but that did not work. It still hung.
you can use IdleHandler
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.xxx);
final AdapterData data = getData();
IdleHandler handler = new IdleHandler() {
#Override
public boolean queueIdle() {
myAdapter = new MyAdapter(MyActivity.this, data);
lvMyList.setAdapter(myAdapter);
return false;
}
};
Looper.myQueue().addIdleHandler(handler);
}

AsycTask thread inside doInBackground runs after PostExecution has started

I am using AsyncTask and there are threads running inside the doInBackground method, isn't the purpose of AsyncTask is to let all the code finish executing inside the doInBackground and THEN go to PostExecute? Then why is it that some of my threads are running after the code block in PostExecution has started?
What should I do to solve this problem?
public class myActivity{
#Override
protected void onCreate(Bundle savedInstanceState) {
...
}
#Override
public void onClick(View view) {
new myTask().execute();
}
class myTask extends AsyncTask<Void, Void, Void> {
Boolean success;
#Override
protected void onPreExecute() {
success = true
}
#Override
protected Void doInBackground(Void... params) {
try {
Callback callback = new Callback() {
public void successCallback(String name, Object response) {
}
public void errorCallback(String name, error) {
success = false;}
};
} catch (Exception e) {
success = false;
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
if (success == true){
// do something
}
}
}
}
It is inside the error callback, that I want the success field to change to false. But the error callback runs after the postExecute method.
I think that you misunderstand the threading model.
AsyncTask does indeed execute doInBackground first, on a background thread, and then executes onPostExecute on the foreground thread, passing it the result from doInBackground.
However, from the wording of your question, it sounds like you are starting new threads from doInBackground. I'm sure that doInBackground does indeed complete before onPostExecute starts, but there is nothing that would cause the AsyncTask to wait for your additional threads to complete as well.
Edit:
It looks like you could skip the AayncTask altogether. The reason that you have callbacks is probably that method is already asynchronous
But note that you are only creating the callback, never using it. Perhaps you just left that part out?

Android : how to implement PullToRefreshListView in proper way

i am new to Android and currently start learning how to implement PullToRefreshListview by using this library of chrisbanes. can you guys please explain to me, where should i put my code to call API for getting data, and which part should i set the(ImageBitmap) after i get the data (image URL) from API. as i know, we should do something in background to avoid the UI freeze when loading Image to UI, but i am not sure. Please help.
The following is the sample code from the library:
please explain to me what should i do in GetDataTask and onPostExecute. In the case like loading image.
#Override
public void onRefresh(PullToRefreshBase<ListView> refreshView) {
// Do work to refresh the list here.
new GetDataTask().execute();
}
private class GetDataTask extends AsyncTask<Void, Void, String[]> {
#Override
protected String[] doInBackground(Void... params) {
// Simulates a background job.
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
}
return mStrings;
}
#Override
protected void onPostExecute(String[] result) {
mListItems.addFirst("Added after refresh...");
mAdapter.notifyDataSetChanged();
// Call onRefreshComplete when the list has been refreshed.
mPullRefreshListView.onRefreshComplete();
super.onPostExecute(result);
}
}
Sorry for the newbie question, i jsust want to confirm it in order to follow the standard. sorry for my bad english
I think you should put your GetDataTask in a separated class with a Listener. This is an example of a listener you can have:
public abstract class RemoteCallListener implements IRemoteCallListener {
#Override
public abstract void onString(String s); //String is just an example.
#Override
public abstract void onError(Exception e);
}
You should give the listener to your constructor if your async task.
private class GetDataTask extends AsyncTask<Void, Void, String[]> {
RemoteCallListener listener;
public GetDataTask(){
}
public GetDataTask(RemoteCallListener listener){
this.listener = listener;
}
#Override
protected String[] doInBackground(Void... params) {
// Simulates a background job.
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
}
return mStrings;
}
#Override
protected void onPostExecute(String[] result) {
listener.onString(result);
// mListItems.addFirst("Added after refresh...");
// mAdapter.notifyDataSetChanged();
// Call onRefreshComplete when the list has been refreshed.
// mPullRefreshListView.onRefreshComplete();
super.onPostExecute(result);
}
}
To make an instance of the call you should do something like
GetDataTask task = new GetDataTask(yourlistener);
task.execute("your link");
And in your 'controller'class you should make an instance of RemoteCallListener and when onString is called:
mListItems.addFirst("Added after refresh...");
mAdapter.notifyDataSetChanged();
// Call onRefreshComplete when the list has been refreshed.
mPullRefreshListView.onRefreshComplete();
You can also freeze the UI by the Dialogs class from android. An example is given here:
public final static ProgressDialog showLoading(Context c, String title,
String message, boolean indeterminate) {
ProgressDialog p = new ProgressDialog(c);
p.setTitle(title);
p.setMessage(message);
p.setCancelable(false);
p.setIndeterminate(indeterminate);
if (!indeterminate) {
// p.setProgressDrawable( c.getResources().getDrawable(
// R.drawable.progress ) );
p.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
p.setProgress(0);
p.setMax(100);
}
p.show();
return p;
}
But dont forget to close your Dialog!
You can contact me anytime if you have further questions
GetDataTask is used to call your webservice again to get the new list items. These things should be done in doInBackground. Once you get the new list item need to set the new adapter for your listview in onPostExecute.

ProgressDialog within AsyncTask not updated

I am having a problem with ProgressDialog UI being frozen when I start the action in the AsyncTask.
My problem is somewhat different than the bunch of other similar question because the my background task consists of two parts:
- first part (loadDB()) is related to the database access
- second part (buildTree()) is related to building the ListView contents and is started with runOnUiThread call
The progress dialog is correctly updated during the 1st part of the task, but not during the 2dn part.
I tried moving the buildTree part in the AsyncTask's onPostExecute but it doesn't help, this part of the code still causes the progress to freeze temporarily until this (sometimes quite lengthy) part of the work is done. I can not recode the buildTree part from scratch because it is based on external code I use.
Any tips on how to resolve this? Is there a method to force updating some dialog on screen?
The code goes here:
public class TreePane extends Activity {
private ProgressDialog progDialog = null;
public void onCreate(Bundle savedInstanceState) {
// first setup UI here
...
//now do the lengthy operation
new LoaderTask().execute();
}
protected class LoaderTask extends AsyncTask<Void, Integer, Void>
{
protected void onPreExecute() {
progDialog = new ProgressDialog(TreePane.this);
progDialog.setMessage("Loading data...");
progDialog.show();
}
protected void onPostExecute(final Void unused) {
if (progDialog.isShowing()) {
progDialog.dismiss();
}
}
protected void onProgressUpdate(Integer... progress) {
//progDialog.setProgress(progress[0]);
}
protected Void doInBackground(final Void... unused)
{
//this part does not block progress, that's OK
loadDB();
publishProgress(0);
//long UI thread operation here, blocks progress!!!!
runOnUiThread(new Runnable() {
public void run() {
buildTree();
}
});
return null;
}
}
public void buildTree()
{
//build list view within for loop
int nCnt = getCountHere();
for(int =0; i<nCnt; i++)
{
progDialog.setProgress(0);
//add tree item here
}
}
}
Don't run your whole buildTree() method inside the UI thread.
Instead, run only the changes you want to make to the UI in the UI thread:
protected Void doInBackground(final Void... unused)
{
//this part does not block progress, that's OK
loadDB();
publishProgress(0);
buildTree();
return null;
}
And then:
public void buildTree()
{
//build list view within for loop
int nCnt = getCountHere();
for(int =0; i<nCnt; i++)
{
progDialog.setProgress(0);
runOnUiThread(new Runnable() {
public void run() {
// update your UI here and return
}
});
// now you can update progress
publishProgress(i);
}
}
You should call AsyncTask's publishProgress method and not the progDialog.setProgress(0); as you call.
Also the buildTree shouln't run on the UI thread since it will block it.
run the logic from the doInBackground method.
note that you don't actually build the ListView, rather you should build it's data model.
look here
something like this:
protected Void doInBackground(final Void... unused)
{
//this part does not block progress, that's OK
loadDB();
publishProgress(0);
buildTree();
}
public void buildTree()
{
//build list view within for loop
int nCnt = getCountHere();
for(int =0; i<nCnt; i++)
{
publishProgress(i); //for exmple...
//add tree item here
}
}

ProgressBar display with some delay in on click of option menu

I am facing the issue with displaying progressbar onItem selected in option menu.
My code is here:
case R.id.mnuLogout:
showDialog(Constants.PROGRESS_DIALOG);
closeOptionsMenu();
if(MyApp.IsLoggedOut())
handler.sendEmptyMessage(Constants.LOGOUT);
else
handler.sendEmptyMessage(Constants.ERROR_MSG);
Progressbar is displayed after completion of IsLogged method.
You're calling get() right after the AsyncTask as executed and lose asynchronous behavior because this method waits until task is finished. You should add all the code in try/catch block to AsyncTask.onPostExecute() method and also dismiss the dialog from this method.
void doLogout() {
new LogoutTask().execute();
}
void dispatchLogoutFinished() {
dismissDialog(Constants.PROGRESS_DIALOG);
if (MyApp.IsLoggedOut()) {
// do something
} else {
// do something else
}
}
private class LogoutTask extends AsyncTask<Void, Void, Void> {
protected void onPreExecute() {
TheActivity.this.showDialog(Constants.PROGRESS_DIALOG);
}
protected Void doInBackground(Void... params) {
return null;
}
protected void onPostExecute(Long result) {
TheActivity.this.dispatchLogoutFinished();
}
}
And I don't think you need to send messages to the handler. The dispatchLogoutFinished() is executed on the UI thread, so there's no need for synchronization.

Categories

Resources