ProgressDialog does not want to update the message - android

I just tried to implement a progressdialog and I have some issues to change the text during my long and complex calculations.
for (String aString:myStringArray){
Log.v(TAG, aString);
mProgressDialog.incrementProgressBy(1);
mProgressDialog.setMessage(aString);
}
I can clearly see the incrementProgressBy working and my dialog updating, but the message does not change.
Any idea on how to make that work?
Thank a lot.

Just found the answer, that's working fine:
runOnUiThread(changeMessage);
with that code:
private Runnable changeMessage = new Runnable() {
#Override
public void run() {
//Log.v(TAG, strCharacters);
m_ProgressDialog.setMessage(strCharacters);
}
};

I upload pictures to Firebase in a loop and updating the ProgressDialog each image:
(I am in a Fragment, so I use getActivity() before calling to runOnUiThread())
List<Bitmap> bitmaps;
int picCounter = 1;
...
progressDialog = ProgressDialog.show
(getContext(), "sending...", "just a minute", false, false);
new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < bitmaps.size(); i++) {
String filename = String.valueOf(i);
uploadPic(bitmaps.get(i), "img" + filename, new MyCallback() {
#Override
public void onFinish() {
picCounter++;
Objects.requireNonNull(getActivity()).runOnUiThread(new Runnable() {
public void run() {
progressDialog.setTitle ("upoading " + picCounter + "image from " + bitmaps.size());
}
});
}
});
}
}
}).start();
uploadPic method:
public interface MyCallback { void onFinish ();}
private void uploadPic(final Bitmap bitmap, final String fileName, final MyCallback callback) {
... // uploading to firebase and then:
callback.onFinish();
}

Related

Android Socket.io emits twice instead of once?

I'm using android socket.io but the problem is that emit event runs twice instead of once , i mean that i wrote just one emit code in the onCreate method , but it sends two request for the server ?
I searched alot but not found anything .
I use node js in the backend ,and my code has not any problems .
Is there a bug in socket.io for android ?
Here is my code :
SocketManager.getInstance().connect();
// Creating Bids
final Handler mHandler04 = new Handler(Looper.getMainLooper());
mHandler04.post(new Runnable() {
#Override
public void run() {
SocketManager.getInstance().getSocket().emit("allc", "some");
SocketManager.getInstance().getSocket().on("allcRes", new Emitter.Listener() {
#Override
public void call(final Object... args) {
g.context.runOnUiThread(new Runnable() {
#Override
public void run() {
JSONArray jsonArray = (JSONArray) args[0];
arrayComps.clear();
Log.d(TAG, "run: " + jsonArray);
try {
for (int i = 0; i < jsonArray.length(); i++) {
createView(jsonArray.getJSONObject(i).getString("title"), jsonArray.getJSONObject(i).getString("realprice"), jsonArray.getJSONObject(i).getString("id"), jsonArray.getJSONObject(i).getString("starttime"), jsonArray.getJSONObject(i).getString("img"));
CustomViewCompetition css = (CustomViewCompetition) LinearLayoutItemHolder.getChildAt(i);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
});
}
});
final Handler bidsupdateHandler = new Handler(Looper.getMainLooper());
bidsupdateHandler.post(new Runnable() {
#Override
public void run() {
SocketManager.getInstance().getSocket().on("bidsupdate", new Emitter.Listener() {
#Override
public void call(final Object... args) {
final JSONArray jsonArray = (JSONArray) args[0];
g.context.runOnUiThread(new Runnable() {
#Override
public void run() {
Log.d(TAG, "run in bidsupdate");
try {
for (int i = 0; i < jsonArray.length(); i++) {
bidsMap.put(jsonArray.getJSONObject(i).getInt("key"), jsonArray.getJSONObject(i).getInt("value"));
}
for (int i = 0; i < LinearLayoutItemHolder.getChildCount(); i++) {
CustomViewCompetition cs = (CustomViewCompetition) LinearLayoutItemHolder.getChildAt(i);
Log.d(TAG, "run in cs " + cs.txtCsRealPrice.getText());
}
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
});
}
});
the Problem is when i get the cs.txtCsTitle.getText() it is just showing me one of them
Add this line:
SocketManager.getInstance().getSocket().emit("allc", "some");
just after:
SocketManager.getInstance().connect();
So your code will be like
SocketManager.getInstance().connect();
SocketManager.getInstance().getSocket().emit("allc", "some");
And remove from where you are already using in handler. Also you dont need handlers why you are using handlers? Create your listener and emit your subscription out of handlers it needs to be created or subscribed once. On creation of emitter listener pass views if you need to update any view. then update the views here you may need runnable to update UI on uiThread.
Create Class as follows:
public class YourListener implements Emitter.Listener
{
private yourView view;
public YourListener (View view)
{
this.view = view;
}
#Override
public void call(Object... args)
{
// do your work here
}
}
and replace below code :
SocketManager.getInstance().getSocket().on("allcRes", new Emitter.Listener() {
#Override
public void call(final Object... args) {
g.context.runOnUiThread(new Runnable() {
#Override
public void run() {
JSONArray jsonArray = (JSONArray) args[0];
arrayComps.clear();
Log.d(TAG, "run: " + jsonArray);
try {
for (int i = 0; i < jsonArray.length(); i++) {
createView(jsonArray.getJSONObject(i).getString("title"), jsonArray.getJSONObject(i).getString("realprice"), jsonArray.getJSONObject(i).getString("id"), jsonArray.getJSONObject(i).getString("starttime"), jsonArray.getJSONObject(i).getString("img"));
CustomViewCompetition css = (CustomViewCompetition) LinearLayoutItemHolder.getChildAt(i);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
});
with:
SocketManager.getInstance().getSocket().on("your_subscription", new YourListener (yourView));

How to manually call observer.onNext in rxJava

I am relatively new to RxJava/RxAndroid. I have been using AsyncTask to do my long running tasks before now.
I have converted most of my AsyncTask to RxJava but this one.
The particular problem I am having is calling something like AsyncTask's publishProgress(params); in
the background thread. I need to do this to update the progress of a ProgressBar.
First this is the code in AsyncTask
private static class AddBooksToDatabase extends AsyncTask<String, String, String> {
//dependencies removed
AddBooksToDatabase(AddBooksDbParams params) {
//Removed assignment codes
}
#Override
protected String doInBackground(String... strings) {
//Initializing custom SQLiteOpenHelper and SQLite database
File mFile = new File(mFolderPath);
int booksSize = getFilesInFolder(mFile).size();
String[] sizeList = {String.valueOf(booksSize)};
//The first publishProgress is used to set the max of the progressbar
publishProgress(sizeList);
for (int i = 0; i < booksSize; i++) {
//publishProgress with current item, current file
publishProgress(String.valueOf(i), getFilesInFolder(mFile).get(i).getName());
//Inserting current items in database. Code removed
}
return null;
}
#Override
protected void onPreExecute() {
//Show ProgressBar
}
#Override
protected void onPostExecute(String s) {
//Hide ProgressBar
}
#Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
if (values.length == 1) {
//The first call to publishProgress
mProgressBar.setMax(Integer.parseInt(values[0]));
} else {
//Subsequent calls to publish progress
Log.i(TAG, "Current item is " + values[0] + " and current file is " + values[1]);
infoText.setText(values[1]);
mProgressBar.setProgress(Integer.parseInt(values[0]), true);
}
}
#Override
protected void onCancelled() {
cancel(true);
}
}
Code Using RxJava
final Observable<String[]> addBooksObserver = Observable.create(new Observable.OnSubscribe<String[]>() {
#Override
public void call(Subscriber<? super String[]> subscriber) {
subscriber.onNext(setAddSubscription());
subscriber.onCompleted();
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
private String[] setAddSubscription() {
S//Initializing custom SQLiteOpenHelper and SQLite database
File mFile = new File(mFolderPath);
int booksSize = getFilesInFolder(mFile).size();
String[] sizeList = {String.valueOf(booksSize)};
//The first publishProgress is used to set the max of the progressbar
addBooksObserver.doOnNext(addReturnParams(String.valueOf(sizeList.length), null, null));
for (int i = 0; i < booksSize; i++) {
EpubReader reader = new EpubReader();
//publishProgress with current item, current file*
addBooksObserver.doOnNext(addReturnParams(String.valueOf(sizeList.length),
String.valueOf(i), getFilesInFolder(mFile).get(i).getName()));
//Inserting current item in database. Code removed
}
return null;
}
private String[] addReturnParams(String totalItems, String currentItem, String currentFile) {
return new String[]{totalItems, currentItem, currentFile};
}
The problem is that lines addBooksObserver.doOnNext(addReturnParams( are displaying this error
doOnNext (rx.functions.Action1) cannot be applied to (java.lang.String[])
I don't know have any idea how to fix this because I thought that since setAddSubscription() and addReturnParams(String totalItems, String currentItem, String currentFile) are returning String array then this shouldn't be a problem. Please can you help me out?
you just have to pass the values to the onNext method of your subscriber, not the doOnNext method of your observable!
you also have to subscribe to the service. try something like this for your obserable:
Observable.create(new Observable.OnSubscribe<String[]>() {
#Override
public void call(Subscriber<? super String[]> subscriber) {
setAddSubscription(subscriber);
subscriber.onCompleted();
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<String[]>() {
#Override
public void onCompleted() {
// handle 'oparation is done'
}
#Override
public void onError(Throwable e) {
}
#Override
public void onNext(String[] values) {
if (values.length == 1) {
//The first call to publishProgress
mProgressBar.setMax(Integer.parseInt(values[0]));
} else {
//Subsequent calls to publish progress
Log.i(TAG, "Current item is " + values[0] + " and current file is " + values[1]);
infoText.setText(values[1]);
mProgressBar.setProgress(Integer.parseInt(values[0]), true);
}
}
});
you also need to modify your private methods a little bit:
private void setAddSubscription(Subscriber<? super String[]> subscriber) {
//Initializing custom SQLiteOpenHelper and SQLite database
File mFile = new File(mFolderPath);
int booksSize = getFilesInFolder(mFile).size();
String[] sizeList = {String.valueOf(booksSize)};
//The first publishProgress is used to set the max of the progressbar
subscriber.onNext(addReturnParams(String.valueOf(sizeList.length), null, null));
for (int i = 0; i < booksSize; i++) {
EpubReader reader = new EpubReader();
//publishProgress with current item, current file*
subscriber.onNext(addReturnParams(String.valueOf(sizeList.length),
String.valueOf(i), getFilesInFolder(mFile).get(i).getName()));
//Inserting current item in database. Code removed
}
}
private String[] addReturnParams(String totalItems, String currentItem, String currentFile) {
return new String[]{totalItems, currentItem, currentFile};
}
You can use Subject to call onNext() manually like this:
Subject<Event> event = Subject.create();
Now call the onNext() for sending event like:
event.onNext("event");
Finally you can return Observable by using this code:
event.toFlowable(BackpressureStrategy.LATEST)
.toObservable();
Your Observer should be like Observable.create(new Observable.OnSubscribe<String>() & in your call method you should loop through the StringArray & pass it to onNext for example:
#Override
public void call(Subscriber<? super String> subscriber) {
for(String val : setAddSubscription()) {
subscriber.onNext(val);
}
subscriber.onCompleted();
}
now onNext shall return you individual items & onCompleted will be called upon the loop is finished.
Edit
myObserver.subscribe(new Subscriber<String>() {
#Override
public void onCompleted() {
// handle completion.
}
#Override
public void onError(Throwable e) {
}
#Override
public void onNext(String value) {
// do whatever with each value passed to onNext
}
});
Observable.create(emitter -> {
for (int i = 0; i < 10; i++) {
int[] ii = {i, i * 2};
emitter.onNext(ii);
}
emitter.onComplete();
}).observeOn(AndroidSchedulers.mainThread()).subscribeOn(Schedulers.io()).subscribe(o -> {
// update progress
int[] i = (int[]) o;
Toast.makeText(SearchActivity.this, "oftad " + i[0] + " - " + i[1], Toast.LENGTH_SHORT).show();
}, t -> {
// on error
Toast.makeText(SearchActivity.this, t.getMessage(), Toast.LENGTH_SHORT).show();
}, () -> {
// progress tamom shod
Toast.makeText(SearchActivity.this, "completed", Toast.LENGTH_SHORT).show();
});

I want to know if my code is thread-safe

I have a code like this, which makes a anonymous thread
everytime the loop goes. And the length of cityArray is 17.
for(int i=0; i<cityArray.length; i++)
{
final int finalI = i;
new Thread(new Runnable() {
#Override
public void run() {
setMarkerIcon(cityArray[finalI]);
}
}).start();
}
And it calls the setMarkerIcon method, which runs the getBestMarkerItemfromArrayList, then runs runOnUiThread to update view.
public void setMarkerIcon( final String city ){
final MarkerItem markerItem = getBestMarkerItemfromArrayList(city);
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
Log.i(TAG, "run: ");
if(markerItem != null){
Glide.with(getContext())
.load(R.drawable.back_level3)
.asBitmap()
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(new SimpleTarget<Bitmap>() {
#Override
public void onResourceReady(Bitmap bitmap, GlideAnimation<? super Bitmap> glideAnimation) {
Log.i(TAG, "onResourceReady: " + map.getMarkers().size() + "__" + city);
for (int i = 0; i < markerOptions.length; i++) {
if (map.getMarkers().get(i).getData().equals(city)) {
map.getMarkers().get(i).setIcon(BitmapDescriptorFactory.fromBitmap(createDrawableFromView(city, bitmap)));
break;
}
}
}
});
The code works well, and there seems to be no problem at the moment.
But I just want to make sure that I am using the thread correctly.
Thanks.

How to call a asyncTask several times inside a loop- one after another

Actually what i am trying to do is that call an asyncTask several times inside a loop. So, first time the asyncTask will start immediately and from second time onwards, it will check whether the AsyncTask has been finished-if finished than again call it with different values.
Below is my code for the activity:
In onCreate()
btnUpload.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
count_response = 0;
newUploadWithSeparate();
}
});
The newUploadWithSeparate() method:
private void newUploadWithSeparate()
{
responseString_concat = "";
if(filePath.length > 0)
{
for(int i=0;i<filePath.length;i++)
{
count_response = i;
if(i == 0)
{
uploadAsync.execute(filePath[0]);
mHandler = new Handler() {
#Override public void handleMessage(Message msg) {
String s=(String)msg.obj;
Log.d("logIMEI","\n Response from Asynctask: " + s);
str_response_fromAsync = s;
}
};
}
else
{
uploadAsync.getStatus();
while(uploadAsync.getStatus() == AsyncTask.Status.RUNNING) // this while loop is just to keep the loop value waitining for finishing the asyncTask
{
int rx = 0;
}
if(uploadAsync.getStatus() != AsyncTask.Status.RUNNING)
{
if(uploadAsync.getStatus() == AsyncTask.Status.FINISHED)
{
if(str_response_fromAsync != "" || !str_response_fromAsync.equals("") || !str_response_fromAsync.isEmpty())
{
uploadAsync.execute(filePath[i]);
x = i;
mHandler = new Handler() {
#Override public void handleMessage(Message msg)
{
String s=(String)msg.obj;
Log.d("logIMEI","\n Response from Asynctask_" + x + ": " + s);
str_response_fromAsync = s;
}
};
}
}
}
}
}
}
}
And the asyncTask:
private class UploadFileToServer extends AsyncTask<String, Integer, String>
{
#Override
protected void onPreExecute()
{
super.onPreExecute();
}
#Override
protected String doInBackground(String... params)
{
return uploadFile(params[0]);
}
private String uploadFile(String pr)
{
//inside here calling webservice and getting a response string as result.
MyWebsrvcClass mycls = new MyWebsrvcClass();
return responseString_concat = mycls.Call(xxx,yyy) ;
}
#Override
protected void onPostExecute(String result)
{
Log.d("logIMEI" , "\n count_response : "+ count_response + " fileprath_len : " + filePath.length);
Message msg=new Message();
msg.obj=result.toString();
mHandler.sendMessage(msg);
super.onPostExecute(result);
}
}
Now the problem is that its not working as expected. The first time when value of i is equals 0 than the AsyncTask gets called and after that its not getting called anymore.
Plus, when first time AsyncTask is called- its still not directly entering to onPostExecute(). When the loop ends totally and newUploadWithSeparate() method ends then the onPostExecute() is working.
Any solutions for this or any other way to do this job done for using AsyncTask inside loop?
You cannot call execute() on the same object more than once. So create a new instance of UploadFileToServer for each iteration of the loop.

Disable loading in Pull to refresh listview

I am having Pull to Refresh https://github.com/chrisbanes/Android-PullToRefresh as given in this link. Everything works fine. But when my list item finishes, the loading icon and pull to refresh label is still visible. So, how to disable the scrolling when end of list reached?
mainListView.setOnRefreshListener(new OnRefreshListener() {
#Override
public void onRefresh(PullToRefreshBase refreshView) {
String total_bk_count = subCategory .getTotal_Book_Count();
count_of_book = Integer.parseInt(total_bk_count);
listCountt = mainbooksAdpater.getCount();
Log.e("StroreActivity","Total book count---====----====---+"+count_of_book);
Log.e("StroreActivity","list Count---====----====---+"+listCountt);
if(listCountt < count_of_book)
{
int bookCount = Common.getBookCountNumber();
Common.setBookCount(bookCount+1);
String refresh_Pull_Url = Common.getUrlForeCategoryBooks(id, Common.NUMBER_OF_BOOKS_PER_REQUEST);
Log.e("Rathis to Check url", Common.getUrlForeCategoryBooks(id, Common.NUMBER_OF_BOOKS_PER_REQUEST));
PulltoRefreshAsync onCatBooksTaskScroll = new PulltoRefreshAsync(Common.getUrlForeCategoryBooks(id, Common.NUMBER_OF_BOOKS_PER_REQUEST));
onCatBooksTaskScroll.execute();
Log.e("StroreActivity","Total Book count::" + book_count_no);
}
else
{
mainListView.setMode(Mode.DISABLED);
Toast.makeText(getApplicationContext(), "end of list", Toast.LENGTH_SHORT).show();
}
}
});
Asynctask Class:
public class PulltoRefreshAsync extends AsyncTask<Object,Object,Object> {
int refreshCount;
String refresh_URL;
public PulltoRefreshAsync(String url) {
refresh_URL = url;
}
/*
* PulltoRefreshAsync(int i) { refreshCount = i; }
*/
#Override
protected void onPreExecute() {
super.onPreExecute();
Log.e("Checking Purpose", refresh_URL);
}
#Override
protected String doInBackground(Object... arg0) {
JsonParserRefresh jp = new JsonParserRefresh();
Log.e("StroreActivity","Array to String::" + refresh_URL);
String jsonString = jp.getJSONFromURL(refresh_URL);
Log.e("StroreActivity","JsonString::" + jsonString);
jsonParseForCategoryBooksGridScroll(jsonString);
return null;
}
#Override
protected void onPostExecute(Object result) {
super.onPostExecute(result);
/*
* if(mProgressDialog.isShowing()) { mProgressDialog.dismiss(); }
*/
final MainBooksAdapter mainbooksAdpater = new MainBooksAdapter(
StoreActivity.this, R.layout.aa, mainBooksList);
final int old_pos = mainListView.getRefreshableView()
.getFirstVisiblePosition() + 1;
mainListView.setAdapter(mainbooksAdpater);
tvvisiblebookCount.setText("" + mainbooksAdpater.getCount());
/*if(listCountt < count_of_book)
{
mainListView.setMode(Mode.DISABLED);*/
mainListView.post(new Runnable() {
#Override
public void run() {
mainListView.onRefreshComplete();
mainListView.getRefreshableView().setSelection(old_pos);
}
});
//}
mainbooksAdpater.notifyDataSetChanged();
}
}
For other people who might have similat issue:
you don't have to implement it this way
mainListView.post(new Runnable() {
#Override
public void run() {
mainListView.onRefreshComplete();
mainListView.getRefreshableView().setSelection(old_pos);
}
});
instead do just like this :
mainListView.onRefreshComplete();
one more thing I noticed, instead of saving the old pos value to get back to it, why not just use notifyDataSetChanged it leaves the position of the list the way it is, just try not to re-instanciate you list, i.e: mainBooksList = ..., instead try this:
mainBooksList.clear();
mainBooksList.addAll(YOUR DATA);
adapter.notifyDataSetChanged();
voila!
hope this helps someone

Categories

Resources