I want to 开发者_如何学Cdisplay toast message inside timer and I used the following code :
timer.scheduleAtFixedRate( new TimerTask()
{
public void run()
{
try {
fun1();
} catch (Exception e) {e.printStackTrace(); }
}
}, 0,60000);
public void fun1()
{
//want to display toast
}
And I am getting following error:
WARN/System.err(593): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
WARN/System.err(593): at android.os.Handler.(Handler.java:121)
WARN/System.err(593): at android.widget.Toast.(Toast.java:68)
WARN/System.err(593): at android.widget.Toast.makeText(Toast.java:231)
Thanks.
You can't make UI updates inside separate Thread, like Timer. You should use Handler object for UI update:
timer.scheduleAtFixedRate( new TimerTask() {
private Handler updateUI = new Handler(){
@Override
public void dispatchMessage(Message msg) {
super.dispatchMessage(msg);
fun1();
}
};
public void run() {
try {
updateUI.sendEmptyMessage(0);
} catch (Exception e) {e.printStackTrace(); }
}
}, 0,60000);
The easiest way (IMO) is:
new Timer().scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
final String message = "Hi";
MyActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MyActivity.this, message, Toast.LENGTH_SHORT).show();
}
});
}
});
The key being MyActivity.this.runOnUiThread(Runnable).
create a Handler
and display toast in this
private Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
// Toast here
}
};
You need access to the Context of the application to be able to do this. Try creating your own class which takes the context as input parameter:
private class MyTimerTask extends TimerTask {
private Context context;
public MyTimerTask(Context context) {
this.context = context;
}
@Override
public void run() {
Toast.makeText(context, "Toast text", Toast.LENGTH_SHORT).show();
}
}
Then in your timer:
timer.scheduleAtFixedRate( new MyTimerTask(this), 0,60000);
I wanted to make a simple project that could display a Toast in a Timer. The Timer would be started using a service. Then, the Timer starts when the service is started and stops when service is stopped.
Class 1
package com.example.connect;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.Button;
public class MainActivity extends Activity {
Button button1,button2;
private Handler mHandler = new Handler();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button1=(Button)findViewById(R.id.button1);
button2=(Button)findViewById(R.id.button2);
}
public void Start(View v)
{
startService(new Intent(MainActivity.this , Connect_service.class));
}
public void Stop(View v)
{
stopService(new Intent(MainActivity.this , Connect_service.class));
}
}
Class 2
package com.example.connect;
import java.util.Timer;
import java.util.TimerTask;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.widget.Toast;
public class Connect_service extends Service{
Timer timer = new Timer();
TimerTask updateProfile = new CustomTimerTask(Connect_service.this);
public void onCreate() {
super.onCreate();
Toast.makeText(this, "Service Started", Toast.LENGTH_SHORT).show();
timer.scheduleAtFixedRate(updateProfile, 0, 5000);
}
@Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
Toast.makeText(this, "Service Stopped", Toast.LENGTH_SHORT).show();
timer.cancel();
}
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
}
Class 3
package com.example.connect;
import java.util.TimerTask;
import android.content.Context;
import android.os.Handler;
import android.widget.Toast;
public class CustomTimerTask extends TimerTask {
private Context context;
private Handler mHandler = new Handler();
public CustomTimerTask(Context con) {
this.context = con;
}
@Override
public void run() {
new Thread(new Runnable() {
public void run() {
mHandler.post(new Runnable() {
public void run() {
Toast.makeText(context, "In Timer", Toast.LENGTH_SHORT).show();
}
});
}
}).start();
}
}
I'm trying to make my own toast with my own views.
I've successfully combined your approaches. The following code allows me to show toasts and change/remove views without crashing, just change the parameters of the MyTimerTask
constructor to whatever you need to work on.
public void yourFunction(){
Timer timer = new Timer();
MyTimerTask mtc = new MyTimerTask(this.getContext(), tvNotice);
timer.schedule(mtc, 1000);
}
private class MyTimerTask extends TimerTask {
private TextView tv;
private Context context;
public MyTimerTask(Context pContext, TextView pTv) {
this.tv = pTv;
this.context = pContext;
}
@Override
public void run() {
updateUI.sendEmptyMessage(0);
}
private Handler updateUI = new Handler(){
@Override
public void dispatchMessage(Message msg) {
super.dispatchMessage(msg);
tv.setText("TextView Message");
Toast.makeText(context, "Toast Message", 0).show();
}
};
}
You have to call UIThread for showing Toast, not from timer thread.
Else call UI thread from that timer thread.
This link will help you,
http://developer.android.com/resources/articles/timed-ui-updates.html
and this
http://developer.android.com/guide/appendix/faq/commontasks.html#threading
精彩评论