I am using picasso to save image to disk on tap of a button by the user and I want to generate a feedback in the form of a Toast to the user that the image has been downloaded.
For this, I am trying to run a toast on the UI Thread by using the following code::
((AppCompatActivity)context).runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
}
});
Which is not running. The image is downloaded and is also visible in the gallery of my app, but the Toast Does not show up. Can someone tell me if I am actually doing this right or should it be done some other way?
FYI: This code is being run in the onBitmapLoaded() method of Target object that I am passing to Picasso to download the Image into; The 'context' object here refers to the current Activity's context.
Any help would be appreciated :)
After doing a lot of search on net I got the answer. You need to display toast on main thread not on background thread. Following code will do the work
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
#Override
public void run() {
//Display toast here
}
});
Use the method that has a callback, there you can define a message for success and error.
final ImageView view = new ImageView(this);
Picasso.with(this).load("http://i.imgur.com/DvpvklR.png").into(view, new Callback() {
#Override
public void onSuccess() {
Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
}
#Override
public void onError() {
}
});
Edit: Add line of the placeholder
Related
I have a legacy IntentService that attempts to use Toast messages to display error messages.1 I'd like the messages to be displayed, and have added code to get them on the correct thread. The simplest change would be to pass in the constructed Toast object and then display it on the UI thread. However, the Toast only displays if I make it in the posted runnable, not if I pass in a pre-made Toast.
This works:
#Override
protected void onHandleIntent(Intent intent) {
showToast("Error", Toast.LENGTH_LONG);
}
private void showToast(final String msg, final int duration) {
new Handler(getMainLooper()).post(new Runnable() {
#Override
public void run() {
// Make and show the toast in the posted runnable
Toast.makeText(getApplicationContext(), msg, duration).show();
}
});
}
This doesn't work:
#Override
protected void onHandleIntent(Intent intent) {
// Make the toast here
Toast myToast = Toast.makeText(getApplicationContext(), "Error", Toast.LENGTH_LONG);
showToast(myToast);
}
private void showToast(final Toast toast) {
new Handler(getMainLooper()).post(new Runnable() {
#Override
public void run() {
// Show the toast here
toast.show();
}
});
}
In both cases, the context is the application context, and I didn't see anything in the source that would cause one version to work, but the other not. Instead the latter has the same problems as if the Toast was shown directly in the IntentService: "Handler (android.os.Handler) {...} sending message to a Handler on a dead thread", Toast not disappearing, etc.
Why does the Toast have to be made on the main thread instead of just shown there?
1. Legacy = I don't think displaying error messages in Toasts is great UI, and I don't think services displaying messages to users directly is a good idea, but that's the code I was handed and I'd like to make it this little bit better.
In the second code that you've posted, the Toast is created in the background thread which has a looper and handler set up (that is the point of IntentService).
The toast uses the current thread's looper to create a handler, but once the IntentService is finished processing the work in onHandleIntent it stops itself (if there aren't other intents to process) - destroying the thread that your Toast's handler is relying on.
line 327: https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/android/widget/Toast.java
Making the toast in the runnable works because at that point, the current thread is the UI thread.
public void upload_prescription()
{
dialog = ProgressDialog.show(MainActivity.this, "","Uploading file...", true);
new Thread(new Runnable()
{
public void run()
{
runOnUiThread(new Runnable()
{
public void run()
{
// option1 upload_image.uploadFile(uploadFilePath);
}
}
);
//option2 upload_image.uploadFile(uploadFilePath);
deleteImageFromGallery(delete_image_id + "");
}
}
).start();
}
Hey i tried above code to upload image onto server.it runs well if i use the option 2 mentioned on the code. but if i put the code on the option 2.it gives me this error.
android.os.NetworkOnMainThreadException.
i think option 2 is better because it give a separate thread to complete the though it does not work properly
Note : I know there are many questions related to this, but still I am not convince, so asking.
I am getting cant create handler inside thread that has not called looper.prepare when I try to show the dialog.
Here is my code...
//this method is called from a different method based on some condition which is inturn called on click a button
private void download() {
thread = new Thread() {
public void run() {
/**** Downloads each tour's Tour.plist file ****/
try {
// do many heavy operations here, like download,
//calling web webvice and starting another activity
This comes at the end
Intent toAudio = new Intent(TourDescription.this,Audio.class);
startActivity(toAudio);
} catch (Exception e) {
}
}
};
thread.start();
}
Now before this actity gets called I am trying to show a dialog. I am trying to place that just before calling Intent.
Can any body please tell me how to do this, as I am not understanding how to solve this
you cannot show a dialog from a child thread.
A dialog can only be showed from within the UI thread/main Thread.
try this from inside the child thread
runOnUiThread(new Runnable() {
#Override
public void run() {
// TODO show dialog....
}
});
I am new to android i am trying to create a new thread to invoke another method.
But don't why it is throwing the error.
here is my stub
void test()
{
int i=0;
Toast.makeText(getApplicationContext(), "Testing", Toast.LENGTH_SHORT).show();
}
public void Button2_Click(View v)
{
Thread thread = new Thread()
{
#Override
public void run() {
test();
}
};
thread.start();
}
You can't manipulate the UI from other threads than the main thread, and launching a Toast involves the user interface.
change your test function
void test()
{
int i=0;
Log.d("Test","Testing");
}
now if the thread works you will se a log inside LogCat. If you want to display a Toast from another thread, you must use Handler or runOnUiThread.
Do this is Handler
like this http://www.tutorialforandroid.com/2009/01/using-handler-in-android.html
you can not put Toast inside a Thread. Remove your Toast message from your code. It will work fine.
This is how you can do it.
`new Thread(new Runnable() {
public void run() {
Bitmap b = loadImageFromNetwork();
mImageView.setImageBitmap(b);
}
}).start();
'
Its a bracket mismatch.
If you absolutely must Toast, you should use the runOnUIThread() method and pass it a new Runnable() anonymous class that Toasts in the run() method.
Irrelevantly, this doesn't seem to make a whole lot of sense. Perhaps you want to make test() static. Maybe post a better idea of what you'd like to do and exactly what error you're getting?
I am having a problem trying to refresh a View in an Android application. I have a button that have a image and what I need to do is to change the image when someone clicked the button.
Where is the problem? The image don't refresh until the activity finished proccessing the code. Any idea how I can refresh the image as soon as It execute the instruction
buttton1.setBackgroundDrawable(getResources().getDrawable(R.drawable.f1));
Have you considered using the xml side and have the drawables as selectors as then the selectors will get chosen by the particular key/touch event to display the correct graphic..
Try running your method that does your processing from a thread.
ficha1.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
Button bot = (Button) findViewById(R.id.boton1);
bot.setBackgroundDrawable(getResources().getDrawable(R.drawable.f2));
//ficha.setText(fichas.get("boton1").toString());
new Thread(
new Runnable() {
public void run() {
controlJugada(fichas.get("boton1").toString(), bot);
}
}
).start();
}
});
I solved a similar problem by putting the offending code in a post delayed handler with a zero delay.
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
// code slowing things down here
}
}, 0);
The first thing you do in the onclick listner is change the backgrount of the button