notifyDataSetChanged is not working for Thread - android

I am fetching messages from the server and storing in local db by using Service. I need to create new Thread for volley response if I won't do so the UI lags so much but the listview is updating. Now after creating new Thread the UI is not lagging anymore but its not updating the listview. Below is my service class code.
ChatService.java
StringRequest stringRequest=new StringRequest(Request.Method.GET, url.replaceAll(" ","%20"), new Response.Listener<String>() {
#Override
public void onResponse(final String response) {
networkThread=new Thread(new Runnable() {
#Override
public void run() {
Gson gson=new Gson();
chatResponse=gson.fromJson(response,GetAllChatResponse.class);
for (Object obj:chatResponse.getData()) {
Log.d("conversation response",""+((ChatDataResponse) obj).getMessage());
sqLiteDataProvider.insertMessage(true,(ChatDataResponse) obj);
}
Log.d("conver","ok");
sendWaResult();
}
});
networkThread.start();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d("convo error",""+error.getMessage());
}
});
MySingleton.getInstance(getApplicationContext()).addToRequestQueue(stringRequest);
public void sendWaResult(){
final Intent intent=new Intent(KYOWA_RESULT);
try{
Looper.prepare();
} catch (Exception e) {}
Handler handler = new Handler();
handler.post(new Runnable() {
#Override
public void run() {
waBroadcastManager.sendBroadcast(intent);
stopSelf();
}
});
}`
While on the other hand in fragment I want to notify my listview that the database has been updated by following code.
ChatFragment.java
receiver=new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
ChatFragment.this.getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
getChat();
}
});
}
};
private void getChat() {
new AsyncTask<Void,Void,ArrayList<ChatListDataResponse>>(){
#Override
protected ArrayList<ChatListDataResponse> doInBackground(Void... voids) {
return sqLiteDataProvider.getChatList();
}
protected void onPostExecute(ArrayList<ChatListDataResponse> list)
{
listDataResponses = list;
if (chatListAdapter==null){
chatListAdapter=new ChatListAdapter(getContext(),listDataResponses);
mListView.setAdapter(chatListAdapter);
}else {
chatListAdapter.updateChatList(listDataResponses);
}
}
}.execute();
And I am notifying my listview by custom BaseAdapter.
ChatListAdapter.java
public void updateChatList(ArrayList<ChatListDataResponse> numbers){
listDataResponses.clear();
listDataResponses.addAll(numbers);
this.notifyDataSetChanged();
this.notifyDataSetInvalidated();
}
Result I am getting: For the very first time after storing the api response into local db the listview stays blank. And on everytime calling ChatService the listview is not updating.
Result I want: I want to notify the listview whenever ChatService gets called.

Try Handler to update UI, because Threads don't give confirmation to work on UI related work :
new Handler().post(new Runnable() {
public void run() {
//UI updation code
}
});
or try :
runOnUiThread(new Runnable() {
public void run() {
//UI updation code
}
});

I would suggest you to use AsyncTask<Void, Void, Void>(), override doInBackground() with your code, and inside onPostExecute() perform the
adapter.notifyDataSetChanged()

Related

Best way handle result from thread on UI

I want to save data to DB in new Thread and after that show toast on the UI.
Method for saving:
public void addToBasket(String text) {
new Thread(() -> {
//emulate save
try {
Thread.sleep(5000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
//after that I need say ti UI thread - show Toast!
}).start();
}
I call this method:
BasketService.me().addToBasket(result.getContents());
I do now want use AsyncTask for this. Please tell me the best way to implement such tasks
batter to use:
runOnUiThread(new Runnable() {
public void run() {
//Do what ever you want do man
}
});
runOnUiThread() method to manipulate your UserInterface from background threads.
In case of callback from a nonUi thread to Ui thread you can use runOnUiThread()(As specified above) or Handler. Below is a example of using handler.
protected static final Handler mainThreadHandler = new Handler(Looper.getMainLooper());
protected void onSuccessInMainThread(final R result, final Bundle bundle) {
mainThreadHandler.post(new Runnable() {
#Override
public void run() {
callback.onSuccess(result, bundle);
}
});
}
protected void onErrorInMainThread(final Exception error) {
mainThreadHandler.post(new Runnable() {
#Override
public void run() {
callback.onError(error);
}
});
}

Show Toast in a Thread of a Service

Hi i know there are lot of answers to this topic. But I tried a lot and it doesn't work. I want to show a toast inside a thread of a service. How can i solve this problem. Using getApplicationContext() etc. doesn't work.
I start the Service from an Activity (no bounding).
public class CarDataService extends Service {
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
...
startThreadUpdatingDatabase();
Toast.makeText(this, message, Toast.LENGTH_LONG).show(); //it works
}
private void startThreadUpdatingDatabase(){
Log.d("Database", "startThreadUpdatingDatabase(was called)");
new Thread(new Runnable() {
public void run(){
..
// here i want to use a toast!!!
}
}).start();
}
}
Thank you!
You have to start the thread:
new Thread(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(),"Your message",Toast.LENGTH_LONG).show();
}
}).start();
public Contect context;
member variable
onStartCommand(){
context = getApplicationContext)
}
acquivre reference to the context before you start the thread
new Thread(new Runnable() {
#Override
public void run() {
Toast.makeText(context,"Your message",Toast.LENGTH_LONG).show();
}
}).start();
and there you go
use AsyncTask instead that helps in context management
http://www.androidsnippets.com/use-toast-wherever-you-want
Handler h = new Handler(context.getMainLooper());
h.post(new Runnable() {
#Override
public void run() {
Toast.makeText(context,message,Toast.LENGTH_LONG).show();
}
});
see if this works out
Show your Toast using UI-Thread
new Thread(new Runnable() {
#Override
public void run() {
// SHOW TOAST
activity.runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(yourContext, "Hello from UI-thread", Toast.LENGTH_SHORT).show();
}
});
//... start DB work
}
}).start();
If you have no access to an activity, so do it this way:
new Thread(new Runnable() {
#Override
public void run() {
// no activity, so use Handler & mainlooper
new Handler(Looper.getMainLooper()).post(
new Runnable() {
public void run() {
// yourContext is Activity or Application context
Toast.makeText(yourContext, "Hello from UI-thread", Toast.LENGTH_SHORT).show();
}
}
);
//... start DB work
}
}).start();
Look at this: Static Way to get Context on android?

progressDialog in onNewIntent

I am using onNewIntent when I am scanning NFC tags. I want to show ProgressDialog while tag is scanned. I tried use a thread but it crashed my app. Is there some way how I can show progressDialog when onNewIntent starts?
public void onNewIntent(Intent intent) {
setIntent(intent);
Thread scanning = new Thread(new Runnable() {
public void run() {
ScanDialog = ProgressDialog.show(BorrowActivity.this,
"Scanning...", "scanning");
}
});
scanning.start();
.
. //next code doing something
.
}
You cannot update or use a UI on another thread:
solution:
Call the Main thread and update the UI inside there
Thread scanning = new Thread(new Runnable() {
public void run() {
runOnUiThread(new Runnable()
{
public void run()
{
ScanDialog = ProgressDialog.show(BorrowActivity.this,
"Scanning...", "scanning");
}
});
}
});
Finally I fixed it with asyncTask.
public void onNewIntent(Intent intent) {
setIntent(intent);
ScanDialog = ProgressDialog.show(BorrowActivity.this,
"Scanning...", "Scanning");
try {
new DoBackgroundTask().execute();
} catch (Exception e) {
//error catch here
}
ScanDialog.dismiss();
And AsyncTask:
private class DoBackgroundTask extends AsyncTask<Integer, String, Integer> {
protected Integer doInBackground(Integer... status) {
//do something
}
protected void onProgressUpdate(String... message) {
}
protected void onPostExecute(Integer status) {
}
}

How to execute an instruction/method immediately after ProgressDialog dismisses?

I am trying to execute the method doSomeWork(); after the ProgressDialog dismisses in my method printing();which seems to be overlapped by the other method and the dialog is not showed up. If I comment method doSomeWork(); the dialog is displayed correctly until the thread is finished.
Here is my method printing();
public void printing()
{
final ProgressDialog printingDialog = ProgressDialog.show(this, "Printing...", "Please wait", true, false);
new Thread(new Runnable() {
#Override
public void run()
{
//something big executing here
}
}).start();
}
He is my method doSomework():
public void doSomeWork(){
Thread receiptPrint = new Thread(new Runnable() {
#Override
public void run() {
//something here
runOnUiThread(new Runnable() {
#Override
public void run() {
//another dialog here
}
});
}
});
}
Here you can see the how I am calling those two methods:
private OnClickListener onClickPrint = new OnClickListener() {
public void onClick(final View v) {
Log.d("Button","Clicked on Print Order Button");
printing();
doSomeWork();
Does anyone know how could I execute doSomeWork() only when printing(); will be completely finished?
This is one of the purposes of an AsyncTask. It would look similar to this:
public void onClick(final View v) {
new AsyncTask<Void, Void, Void>() {
#Override
protected void onPreExecute() {
//Show your progress dialog in here
super.onPreExecute();
}
#Override
protected Void doInBackground( Void... params ) {
printing();
return null;
}
#Override
protected void onPostExecute( Void result ) {
//Dismiss your progress dialog here
doSomeWork();
}
}.execute();
}
Instead of using thread you can use asynchronous task. Show the progress dialog in the preexecute method call the printing method inside the background method after completing printing operation call the doSomeWork() inside the postexecute method.
You can use Handler for that in android. for example consider the following piece of code. you can dismiss the dialogs inside handlers. may it work for you.
private void printing(){
Thread receiptPrint = new Thread(new Runnable() {
#Override
public void run() {
retrieveEmails();
runOnUiThread(new Runnable() {
#Override
public void run() {
try{
//here your code executes
//after code executes do following:
uiHandler.sendEmptyMessage(0);
}catch(Exception ex){
errorHandler.sendEmptyMessage(0);
}
}
});
}
});
receiptPrint.start();
}
final Handler uiHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
//here execute doSomeWork()
}
};
final Handler errorHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
//do other stuff
}
};

Update UI from a thread [duplicate]

This question already has answers here:
Updating Android UI using threads
(4 answers)
Android toast message from a separate thread class
(1 answer)
Closed 9 years ago.
I'm having some trouble trying to update automaticaly a view in my android activity.
The application display some message like a chat. Im using a ListView to put the message with a ArrayAdapter.
I use this metod to update the ListView
public void loadMessages() {
ArrayList<String> messages = this.dbHelper.getMessages();
conversationArrayAdapter.clear();
conversationArrayAdapter.addAll(messages);
conversationArrayAdapter.notifyDataSetChanged();
}
My idea is to put a thread that call that metod, but when i try to do this i have the following error.
Only the original thread that created a view hierarchy can touch its view.
because you are trying to access or update UI elements from Thread . to avoid this error you will meed to use runOnUiThread for updating UI from Thread as :
Your_Current_Activity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
// Update UI here
loadMessages();
}
});
and second solution is use AsyncTask instead of thread
Use this code.
public class MainActivity extends Activity
{
private Timer autoUpdate;
#Override
public void onResume()
{
super.onResume();
autoUpdate = new Timer();
autoUpdate.schedule(new TimerTask()
{
#Override
public void run()
{
runOnUiThread(new Runnable()
{
public void run()
{
updateScore();
}
});
}
}, 0, 5000); // updates each 5 seconds
}
#Override
public void onPause()
{
autoUpdate.cancel();
super.onPause();
}
#Override
public void onCreate(Bundle savedInstanceState)
{
// initialize view layout
super.onCreate(savedInstanceState);
setContentView(R.layout.cleanermain);
super.onResume();
}
private void updateScore()
{
// decide output
// update cricket score
}
}
UI should be updated only from the UI (Main) thread.
Here is a solution using AsyncTask.
public void asyncCallWithSchedule() {
final Handler handler = new Handler();
Timer timer = new Timer();
TimerTask doAsynchronousTask = new TimerTask() {
#Override
public void run() {
handler.post(new Runnable() {
public void run() {
try {
new SearchAsync().execute(txtSearch.getText().toString());
}
});
}
};
timer.schedule(doAsynchronousTask, 0, 2000);
}
}
AsyncTask class:
private class SearchAsync extends
AsyncTask < String, Object, List < Users >> {
#Override
protected List < Users > doInBackground(String...params) {
// Call DB here
return null;
}
#Override
protected void onPostExecute(List < Users > result) {
super.onPostExecute(result);
// Update UI here
}
}
Simple:
public void loadMessages() {
ArrayList<String> messages = this.dbHelper.getMessages();
conversationArrayAdapter.clear();
conversationArrayAdapter.addAll(messages);
new Handler(Looper.getMainLooper()).post(new Runnable() {
public void run() {
conversationArrayAdapter.notifyDataSetChanged();
}
});
}

Categories

Resources