简体   繁体   中英

How to show toast message from background thread

Consider the following code. In Service.onStart() method i have created and started a thread that should show Toast message but it is not working!

public class MyService extends Service{

    private static final String TAG = "MyService";  
    @Override
    public IBinder onBind(Intent intent)
    {
        return null;    
    }       

    @Override   
    public void onCreate()
    {   
    Toast.makeText(this, "My Service Created", Toast.LENGTH_SHORT).show();
         }  
    @Override
    public void onDestroy() 
    {   
    Toast.makeText(this, "My Service Stopped", Toast.LENGTH_SHORT).show();  
    }   
    @Override
    public void onStart(Intent intent, int startid)
    {
      Toast.makeText(this, "My Service Started", Toast.LENGTH_SHORT).show();
      DBIteratorThread dbThread=new DBIteratorThread();
      dbThread.myService=this;
      Thread t1 = new Thread(dbThread);
           t1.start();
    }

}
class DBIteratorThread  implements Runnable
{

    MyService myService;

    public void run()
    {
    //  Toast.makeText(myService, "Thread is Running", Toast.LENGTH_SHORT).show();
            }
}

Do UI stuffs in main/UI thread. Try this:

Handler handler = new Handler(Looper.getMainLooper());

handler.post(new Runnable() {

        @Override
        public void run() {
            //Your UI code here
        }
    });

I have written a class for showing Toasts from background processes. Can be used everywhere, eg in an AsyncTask . You only have to create an instance of this class like

ToastHandler mToastHandler = new ToastHandler(yourContext);

and then call showToast() with your text or resource id and the Toast's duration like you normally would with makeToast() .

Here is the code or the direct download link :

import android.content.Context;
import android.os.Handler;
import android.widget.Toast;

/**
 * A class for showing a <code>Toast</code> from background processes using a
 * <code>Handler</code>.
 * 
 * @author kaolick
 */
public class ToastHandler
{
    // General attributes
    private Context mContext;
    private Handler mHandler;

    /**
     * Class constructor.
     * 
     * @param _context
     *            The <code>Context</code> for showing the <code>Toast</code>
     */
    public ToastHandler(Context _context)
    {
    this.mContext = _context;
    this.mHandler = new Handler();
    }

    /**
     * Runs the <code>Runnable</code> in a separate <code>Thread</code>.
     * 
     * @param _runnable
     *            The <code>Runnable</code> containing the <code>Toast</code>
     */
    private void runRunnable(final Runnable _runnable)
    {
    Thread thread = new Thread()
    {
        public void run()
        {
        mHandler.post(_runnable);
        }
    };

    thread.start();
    thread.interrupt();
    thread = null;
    }

    /**
     * Shows a <code>Toast</code> using a <code>Handler</code>. Can be used in
     * background processes.
     * 
     * @param _resID
     *            The resource id of the string resource to use. Can be
     *            formatted text.
     * @param _duration
     *            How long to display the message. Only use LENGTH_LONG or
     *            LENGTH_SHORT from <code>Toast</code>.
     */
    public void showToast(final int _resID, final int _duration)
    {
    final Runnable runnable = new Runnable()
    {
        @Override
        public void run()
        {
        // Get the text for the given resource ID
        String text = mContext.getResources().getString(_resID);

        Toast.makeText(mContext, text, _duration).show();
        }
    };

    runRunnable(runnable);
    }

    /**
     * Shows a <code>Toast</code> using a <code>Handler</code>. Can be used in
     * background processes.
     * 
     * @param _text
     *            The text to show. Can be formatted text.
     * @param _duration
     *            How long to display the message. Only use LENGTH_LONG or
     *            LENGTH_SHORT from <code>Toast</code>.
     */
    public void showToast(final CharSequence _text, final int _duration)
    {
    final Runnable runnable = new Runnable()
    {
        @Override
        public void run()
        {
        Toast.makeText(mContext, _text, _duration).show();
        }
    };

    runRunnable(runnable);
    }
}

You should be able to use the getApplicationContext() method to get the context with which to show the Toast.

See getApplication() vs. getApplicationContext() for some nice discussion on this.

replace word this with getApplicationContext() The message will then appear

Toast.makeText(this, "My Service Created", Toast.LENGTH_SHORT).show();

the correct :

Toast.makeText(getApplicationContext(), "My Service Created", Toast.LENGTH_SHORT).show();

You can't show a Toast on a thread that is not the activity's ui thread.
you can only run it somewhere else if you use runOnUiThread method so that it runs on the ui thread

Look at this question
Android: Toast in a thread

We use handler for this purpose because it is easy... :)

Steps:

  1. declare a handler in the main activity (onCreate)
  2. a class which is to be run in the background in that create a parameterized constructor . Taking the Context a perimeter .
  3. now create a thread from the main activity and pass the Context of that activity.
  4. now Post to the handler from that another thread (from whichever thread u want to send)
  5. now use this context in the Toast, instead of using getApplicationContext()

It runs well.

mhandler.post(new Runnable() {
    public void run() {
        Toast.makeText(context,"Run ends",Toast.LENGTH_LONG).show();
    }
});

getBaseContext()替换this

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM