我正在尝试开发一个使用线程实现幻灯片放映的应用程序。我正在从SQLite中检索图像路径并在ImageView上显示它们。我遇到的问题是,我感到困惑,所以我无法理解,我从哪个线程调用images()方法,我实际上是在实现幻灯片。
我得到了Logcat,如下所示 -
09-03 13:47:00.248: E/AndroidRuntime(10642): FATAL EXCEPTION: Thread-151
09-03 13:47:00.248: E/AndroidRuntime(10642): android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
09-03 13:47:00.248: E/AndroidRuntime(10642): at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:5908)
09-03 13:47:00.248: E/AndroidRuntime(10642): at com.example.fromstart.MainActivity.images(MainActivity.java:90)
09-03 13:47:00.248: E/AndroidRuntime(10642): at com.example.fromstart.MainActivity$2.run(MainActivity.java:59)
09-03 13:47:00.248: E/AndroidRuntime(10642): at java.lang.Thread.run(Thread.java:841)
MainActivity.java:
public class MainActivity extends Activity
{
ImageView jpgView;
TextView tv;
//adapter mDbAdapter;
adapter info = new adapter(this);
String path;
Handler smHandler = new Handler()
{
public void handleMessage(Message msg)
{
TextView myTextView =
(TextView)findViewById(R.id.textView1);
myTextView.setText("Button Pressed");
}
};
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
jpgView = (ImageView)findViewById(R.id.imageView1);
tv = (TextView) findViewById(R.id.textView1);
}
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
final Runnable runnable = new Runnable()
{
public void run()
{
images();
}
};
int delay = 1000; // delay for 1 sec.
int period = 15000; // repeat every 4 sec.
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask()
{
public void run()
{
smHandler.post(runnable);
}
}, delay, period);
Thread mythread = new Thread(runnable);
mythread.start();
return true;
}
public void handleMessage(Message msg)
{
String string = "sample";
TextView myTextView = (TextView)findViewById(R.id.textView1);
myTextView.setText(string);
}
public void images()
{
try
{
for(int i=0;i<=20;i++)
{
path = info.getpath();
Bitmap bitmap = BitmapFactory.decodeFile(path);
jpgView.setImageBitmap(bitmap);
}
}
catch(NullPointerException er)
{
String ht=er.toString();
Toast.makeText(getApplicationContext(), ht, Toast.LENGTH_LONG).show();
}
}
}
我是android的新手,刚刚开始研究Threads。如果您在我的代码中发现任何错误,请指出这些错误,请建议我,正确的方法来解决这个问题。
提前致谢。
更新
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Handler mHandler = new Handler();
// Create runnable for posting
runOnUiThread(new Runnable()
{
public void run()
{
images();
}
});
int delay = 1000; // delay for 1 sec.
int period = 15000; // repeat every 4 sec.
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask()
{
public void run()
{
images();
}
}, delay, period);
}
public void images()
{
try
{
Toast.makeText(getApplicationContext(), "1", Toast.LENGTH_LONG).show();
path = info.getpath();
Toast.makeText(getApplicationContext(), "2", Toast.LENGTH_LONG).show();
Bitmap bitmap = BitmapFactory.decodeFile(path);
Toast.makeText(getApplicationContext(), "3", Toast.LENGTH_LONG).show();
jpgView.setImageBitmap(bitmap);
Toast.makeText(getApplicationContext(), "4", Toast.LENGTH_LONG).show();
}
catch(NullPointerException er)
{
String ht=er.toString();
Toast.makeText(getApplicationContext(), ht, Toast.LENGTH_LONG).show();
}
}
}
答案 0 :(得分:8)
您无法从线程更新/访问ui。
你有这个
public void run()
{
images();
}
在图片中
jpgView.setImageBitmap(bitmap);
您需要使用runOnUiThread
来更新ui。
runOnUiThread(new Runnable() {
@Override
public void run() {
// do something
}
});
TimerTask也可以在不同的线程上运行。所以你使用了一个处理程序来进行更新。
您可以使用处理程序。
编辑:
Handler m_handler;
Runnable m_handlerTask ;
m_handler = new Handler();
m_handlerTask = new Runnable()
{
@Override
public void run() {
// do something. call images()
m_handler.postDelayed(m_handlerTask, 1000);
}
};
m_handlerTask.run();
如果您仍希望使用计时器任务,请使用runOnUiThread
timer.scheduleAtFixedRate(new TimerTask()
{
public void run()
{
runOnUiThread(new Runnable() {
@Override
public void run() {
images();
}
});
}
}, delay, period);
答案 1 :(得分:4)
要从任何其他线程更新UI,您必须使用
runOnUiThread(<Runnable>);
将更新您的用户界面。
示例:强>
runOnUiThread(
new Runnable()
{
// do something on UI thread Update UI
});