I want display progress bar in activity while loading data and when loading complete, progress bar to be hide (GONE)!
and try this code : (button click to load data)
private void allMoment() {
BTN_ALL.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
TBL_MOMENT = new TableMoment(DB_HELPER);
// MOMENTS = TBL_MOMENT.MOMENT_LIST();
new loadTask().execute();
filterResult();
EDT_SEARCH.setText("");
} catch (Exception e) {
displaySnackBar(v, "خطا:" + "\n" + e.toString());
}
}
});
}
and Task method :
private class loadTask extends AsyncTask<String, Integer, Boolean> {
#Override
protected void onPreExecute() {
PROGRESS_LOADER.setVisibility(View.VISIBLE);
super.onPreExecute();
}
#Override
protected void onPostExecute(Boolean result) {
PROGRESS_LOADER.setVisibility(View.GONE);
adapter.notifyDataSetChanged();
super.onPostExecute(result);
}
#Override
protected Boolean doInBackground(String... params) {
MOMENTS = TBL_MOMENT.MOMENT_LIST();
try {
Thread.sleep(3000);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
and fill recycler with dapter :
private void filterResult() {
try {
adapter = new HistoryAdapter(this, MOMENTS);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(adapter);
} catch (Exception e) {
displayToast(this, "خطای آداپتر:" + "\n" + e.toString());
}
}
but data become load and fill into recyclerview and don't show progress bar
how to fix this problem ?
You have :
new loadTask().execute();
filterResult();
EDT_SEARCH.setText("");
This execute() call returns inmediatly, if you execute an AsyncTask waiting for a result you don't have a result until AsyncTask.doInBackground() returns and AsyncTask.onPostExecuted() is called
Is this filterResult(); time consuming ? ... if the main UI thread is blocked then the UI will be not updated.
How do you want this progress bar to work? You can search for a gif on the Internet, once you find one that suits your criteria you have to display it when you open the activity. When you populate your recyclerView you set the visibility of the gif as GONE.
Related
I am creating an app where user can upload images, I am uploading images one after another using retrofit. Right now I am running a for loop for it, but it is not a good way to do it. I cannot use service because I need progress dialog as well on main screen to let user know upload is happening. Is there a way to maintain some kind of queue to handle this?
You can use the AsyncTask and Retrofit to do it it can be done with the retrofit alone but as I have already done it with AsyncTask have a look.
public class AsyncBulkUpload extends AsyncTask<Boolean, Integer, Boolean> {
private ApiInterface mApiInterface;
private Call<ResponseBody> mResponseBodyCall;
private Response<ResponseBody> mResponseBody;
private RequestBody mRequestBody;
private Service mService;
private Bitmap mItemBitmap;
public int mTotalCount = 0;
public AsyncBulkUpload(Service service) {
mService=service;
mApiInterface = ApiClient.getClient(mService.getApplicationContext()).create(ApiInterface.class);
}
#Override
protected void onPreExecute() {
super.onPreExecute();
mTotalCount = sClosetList.size();
//Show you dialog
}
#Override
protected Boolean doInBackground(Boolean... itsRetry) {
/**
*Check if its retry or not
* if yes don't get the placeholder ids.
* or else hit and get place holder ids
*/
//Run your loop here.
return upload();
}
private Boolean upload() {
if (isCancelled())
return false;
if (sClosetList.size() > 0) {
//Item image
try {
mItemBitmap = Glide.with(mService.getApplicationContext())
.load(sClosetList.get(0).mItemImage)
.asBitmap()
.into(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL)
.get();
} catch (InterruptedException e) {
//Coudnt get the image so cant go further
LogPrint.printError("WHILE GETTING BITMPAP");
return false;
} catch (ExecutionException e) {
//Coudnt get the image so cant go further
LogPrint.printError("WHILE GETTING BITMPAP");
return false;
}
FormBody.Builder bodyBuilder = new FormBody.Builder();
bodyBuilder.add("image", mItemBitmap);
/**
*Label image can or can not be available
*/
mRequestBody = bodyBuilder.build();
mResponseBodyCall = mApiInterface.uploadProducts(mRequestBody);
try {
mResponseBody = mResponseBodyCall.execute();
} catch (IOException e) {
e.printStackTrace();
return false;
}
if (!mResponseBody.isSuccessful()) {
/**
*Some server error try again
*/
return false;
}
}
return true;
}
#Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
//Update your progressbar
}
#Override
protected void onPostExecute(Boolean aBoolean) {
super.onPostExecute(aBoolean);
//Dismiss the dialog
if (aBoolean) {
Toast.makeText(mService, R.string.uploaded_successful, Toast.LENGTH_LONG).show();
}
}
}
I have same stock item , I want to send local database to ApiService, But when I send also I want to update ProgressBar message. I tried the code below but it just shows when all proccessing is finishing.
ProgressDialog progress= new ProgressDialog(this);
progress.setTitle(getResources().getString(R.string.progress_exporting));
progress.setMessage("0/0");
when click button I call below method
public void Export() {
runOnUiThread(new Runnable() {
#Override
public void run() {
findViewById(R.id.btnExportOnlineWithStocktaking).setEnabled(false);
progress.show();
}
});
UpdateUI(send, total);
try {
switch (_stocktakingType) {
case Division: {
switch (_onlineExportType) {
case Item: {
isExport = ExportDivisionStocktakingItems(stocktakingId);
}
break;
}
} catch (Exception ex) {
}
}
// ExportDivisionStocktaking method
public boolean ExportCustomStocktakingItems(int stocktakingId) {
result = Boolean.parseBoolean(SendCustomStocktakingItems(stocktakingId,countResults).responseString);
}
My call back method
public ResponseModel SendCustomStocktakingItems(int selectedDivision, List<ExtensionServiceStocktakingItem> countResults) throws ExecutionException, InterruptedException {
return new SendCustomStocktakingItemsService(flag -> true).execute(String.valueOf(selectedDivision), countResults.toString()).get();
}
//AsyncTask method
public class SendDivisionStocktakingItemsService extends AsyncTask<String, Void, ResponseModel> {
public AsyncResponseSendDivisionStocktakingItems delegate = null;
public SendDivisionStocktakingItemsService(AsyncResponseSendDivisionStocktakingItems delegate) {
this.delegate = delegate;
}
#Override
protected ResponseModel doInBackground(String... parameters) {
RequestHandler requestHandler = new RequestHandler();
JSONObject params = new JSONObject();
try {
params.put("stocktakingItems", parameters[1]);
} catch (JSONException e) {
e.printStackTrace();
}
ResponseModel responseModel = requestHandler.getRequestPostString(UHFApplication.getInstance().apiUrl
+ "/api/MobileService/SendDivisionStocktakingItemsPost?stocktakingID="
+ parameters[0],
parameters[1]);
return responseModel;
}
#Override
protected void onPreExecute() {
UpdateUI(send,total);
super.onPreExecute();
}
#Override
protected void onPostExecute(ResponseModel responseModel) {
super.onPostExecute(responseModel);
if (HttpURLConnection.HTTP_OK == responseModel.httpStatus) {
delegate.processFinish(true);
} else {
delegate.processFinish(false);
}
}
}
//UICalled method
public void UpdateUI(int send, int total) {
runOnUiThread(() -> {
progress.setMessage(send + "/" + total);
Log.d("Send Data : ", send + "/" + total);
if (send == total) {
progress.dismiss();
Toast.makeText(getApplicationContext(), "Succsess", Toast.LENGTH_SHORT).show();
}
});
}
//Update
//Ok I have a simle example how can I use. Below code when I click button I wan to open progress firstly and after that for loop is working and update progres message. I try it but not working.
Firstly For loop is working and after that progres opened.
public void ExportTry(){
UpdateUI(send,total);
runOnUiThread(new Runnable() {
#Override
public void run() {
btnExport.setEnabled(false);
progress.show();
}
});
for(int i=0;i<1000000;i++){
UpdateUI(i,1000000);
}
}
You are missing the part of AsyncTask that will allow you to show progress messages while doInBackground is running. Take a look at onProgressUpdate and publishProgress on the same page.
publishProgress
void publishProgress (Progress... values)
This method can be invoked from doInBackground(Params...) to publish updates on the UI thread while the background computation is still running. Each call to this method will trigger the execution of onProgressUpdate(Progress...) on the UI thread. onProgressUpdate(Progress...) will not be called if the task has been canceled.
I want to update my listview during every new item add to my arraylist during progress dialog showing this is my code
public class Load extends AsyncTask<Void, Void, Void> {
ProgressDialog progress;
#Override
protected void onPreExecute() {
progress = new ProgressDialog(SearchList.this);
progress.setMessage("loading....");
progress.show();
}
#Override
protected Void doInBackground(Void... params) {
// do tracks loading process here, don't update UI directly here
// because there is different mechanism for it
//FlowableBookViewer.webview.loadUrl("javascript:(function(){var txt = window.getSelection();window.name= txt;window.cpjs.sendToAndroid(window.name);})()");
for (int i = 0; i < Globals.currenHtmlList.size(); i++) {
try {
String pageText = FunctionsClass
.readTextFromHtml(Globals.currenHtmlList.get(i));
if (pageText.toLowerCase().contains(
Globals.SelectedText.toLowerCase())) {
String pagename = new File(
Globals.currenHtmlList.get(i)).getName();
SearchItem sitem = new SearchItem();
sitem.setTargetList(Globals.currenHtmlList.get(i));
sitem.setPageNumber(i);
if (pagename.endsWith("html")) {
pagename = pagename.substring(0,
pagename.length() - 5);
} else if (pagename.endsWith("htm")) {
pagename = pagename.substring(0,
pagename.length() - 4);
} else if (pagename.endsWith("xhtml")) {
pagename = pagename.substring(0,
pagename.length() - 6);
}
sitem.setTitleList("Page " + pagename);
founded.add(sitem);
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return null;
}
#Override
protected void onPostExecute(Void result) {
// write display tracks logic here
progress.dismiss(); // dismiss dialog
m_adapter = new OrderAdapter(SearchList.this, R.layout.itemview,
founded);
lv.setAdapter(m_adapter);
lv.setTextFilterEnabled(true);
}
}
in this code the listview items appears after the complete of the for loop which add all the items of sitem object to founded list i want to update listview at every item added to founded .
many thanks
1) Create the adapter before you call the AsyncTask
Move this to your activity/fragment onCreate method:
m_adapter = new OrderAdapter(SearchList.this, R.layout.itemview,
founded);
lv.setAdapter(m_adapter);
lv.setTextFilterEnabled(true);
2) After you add an item in your ArrayList call the onProgressUpdate from the AsyncTask
In your doInBackground method add:
founded.add(sitem);
publishProgress();
3) In the onProgressUpdate method call the notifyDatasetChanged method from your adapter
#Override
protected void onProgressUpdate(Void... v) {
super.onProgressUpdate(v);
m_adapter.notifyDataSetChanged();
}
You can read more about notifyDataSetChanged here.
In my app I performing loading data from web and then displaying it to user. Before loading data app shows progress dialog. I have problem if user locks phone in the middle of loading operation, or server is overloaded and can't respond in time my application freezes, because it doesn't dismiss progress dialog, or in some cases it crashes because lack on needed data.
If some error happened while loading data I want show some dialog to user to let him know about error and ask him should application repeat last request. I tried to use AlertDialog for it, but I haven't succeed.
Here is code of one activity (There is no progress dialog here, but it demonstrates how I loading data):
#EActivity(R.layout.layout_splash)
#RoboGuice
public class SplashScreenActivity extends Activity {
#Inject
private AvtopoiskParserImpl parser;
#Bean
BrandsAndRegionsHolder brandsAndRegionsHolder;
#ViewById(R.id.splash_progress)
ProgressBar progressBar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
loadData();
}
#Background
protected void loadData() {
publishProgress(10);
LinkedHashMap<String, Integer> brands = null;
try {
brands = parser.getBrands();
} catch (IOException e) {
Log.e(e.getMessage());
}
publishProgress(50);
LinkedHashMap<String, Integer> regions = null;
try {
regions = parser.getRegions();
} catch (IOException e) {
Log.e(e.getMessage());
}
publishProgress(70);
populateData(brands, regions);
}
#UiThread
protected void populateData(LinkedHashMap<String, Integer> brands, LinkedHashMap<String, Integer> regions) {
Intent intent = new Intent(SplashScreenActivity.this, SearchActivity_.class);
brandsAndRegionsHolder.brandsMap = brands;
brandsAndRegionsHolder.regionsMap = regions;
publishProgress(100);
startActivity(intent);
finish();
}
#UiThread
void publishProgress(int progress) {
progressBar.setProgress(progress);
}
}
parser.getBrands() and parser.getRegions() are loading data from the web.
I want to do something like this:
boolean repeatRequest = true;
while (repeatRequest) {
try {
brands = parser.getBrands();
repeatRequest = false;
} catch (IOException e) {
Log.e(e.getMessage());
repeatRequest = showErrorDialog();
}
}
But I didn't manage to do so because this code executes in background thread, but dialog should be shown in UI thread.
I believe that it should be standard approach of doing so, but didn't manage to find it.
Any ides how can I implement this?
The best way is to use AsyncTask.
private class LoadDataTask extends AsyncTask<Void, Integer, Object> {
private ProgressDialog mProgress;
protected Object doInBackground(Void... params) {
// This method runs in background
Object result = null;
try {
result = parser.parse();
} catch (Exception e) {
result = e.getMessage();
}
return result;
}
protected void onProgressUpdate(Integer... progress) {
// This method runs in UI thread
mProgress.setProgress(progress[0]);
}
protected void onPreExecute() {
// This method runs in UI thread
mProgress = new ProgressDialog(context);
mProgress.show();
}
protected void onPostExecute(Object result) {
// This method runs in UI thread
mProgress.dismiss();
if (result instance of String) {
// Here you can launch AlertDialog with error message and proposal to retry
showErrorDialog((String) result);
} else {
populateData(result);
}
}
}
I have an AsyncTask which loads Tweets from Twitter.
I also have a PullToRefresh ListView... Whenever i pull to refresh it, the listview immediately clears and as soon as the data has been loaded, it's getting filled into the listview.
I have other ListViews in my App all with the same stuff (PullToRefresh and Async data loading...). On the other ListViews this does not happen. Only on the Twitter ListView. What am I doing wrong?
Here is my Code:
public class TwitterDownloader extends AsyncTask<Void, Void, String> {
final Handler mHandler = new Handler();
public TwitterDownloader() {
}
#Override
public void onPreExecute() {
super.onPreExecute();
}
#Override
protected String doInBackground(Void... params) {
twitter4j.Twitter twitter = new TwitterFactory().getInstance();
listTweets.clear();
List<twitter4j.Status> statuses = null;
try {
statuses = twitter.getUserTimeline(
MainActivity.TWITTER_USERNAME, new Paging(1, 50));
} catch (TwitterException e) {
e.printStackTrace();
Log.e(MainActivity.LOG_TAG, "TwitterException");
}
try {
for (twitter4j.Status status : statuses) {
listTweets.add(status.getText());
}
} catch (NullPointerException npe) {
}
return null;
}
#Override
public void onPostExecute(String unused) {
MyCustomAdapter myAdapter = new MyCustomAdapter(myContext,
R.layout.row_twitter, listTweets);
setListAdapter(myAdapter);
getListView().setTextFilterEnabled(true);
String lastUpdate = (new SimpleDateFormat(
"HH:mm")).format(new Date());
pullToRefreshView.onRefreshComplete();
pullToRefreshView.setLastUpdatedLabel(getString(R.string.last_updated) + ": "
+ lastUpdate);
}
I am not sure about this but in doInBackground method of AsyncTask, you are doing listTweets.clear();. After getting result, you are adding data to it. May be this is causing problems.
I finally fixed it by adding all my clear() statements right before I fill up my list again (which is inside a try catch).
So the new code inside my doInBackground method is:
try {
listTweets.clear();
listUsernames.clear();
listDates.clear();
listImageURLs.clear();
listURLsOfTweets.clear();
for (twitter4j.Status status : statuses) {
listTweets.add(status.getText());
listUsernames.add(status.getUser().getName());
listDates.add(android.text.format.DateFormat
.getDateFormat(getApplicationContext()).format(
status.getCreatedAt())
+ " "
+ android.text.format.DateFormat.getTimeFormat(
getApplicationContext()).format(
status.getCreatedAt()));
listImageURLs.add(status.getUser().getProfileImageURL()
.toString());
StringBuffer address = new StringBuffer();
address.append("http://twitter.com/#!/");
address.append(status.getUser().getScreenName());
address.append("/status/");
address.append(status.getId());
listURLsOfTweets.add(address.toString());
}