Reputation: 10158
in my app in android, i need change background image in image view on 10 seconds once. so that i call a Async Task within a run method. when I execute the app it crashes.
It gives the Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
Exception to me.
I know I have to use Thread, but I do not know how to do so properly. Please help me.
This is my code sample:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
.................
new Thread()
{
public void run()
{
while(true){
try
{
Thread.sleep(5000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
count = count + 1;
new ImageChange().execute();
}
}
}.start();
} // OnCreate End
class ImageChange extends AsyncTask<Void, Void, Void>
{
protected void onPreExecute() {
}
protected void onPostExecute(Void unused) {
iv1.setImageBitmap(b1);
iv2.setImageBitmap(b2);
}
protected Void doInBackground(Void... arg0) {
switch(count){
case 1:
b1 = BitmapFactory.decodeFile(f1.getAbsolutePath());
b2 = BitmapFactory.decodeFile(f2.getAbsolutePath());
break;
case 2:
b1 = BitmapFactory.decodeFile(f2.getAbsolutePath());
b2 = BitmapFactory.decodeFile(f1.getAbsolutePath());
break;
default :
count = 0;
b1 = BitmapFactory.decodeFile(f1.getAbsolutePath());
b2 = BitmapFactory.decodeFile(f2.getAbsolutePath());
break;
}
return null;
}
}
Upvotes: 2
Views: 1735
Reputation: 14426
Probably, the problem is that you must execute the ImageChange.doInBackground()
method in the UI thread. Try to change your code like this:
class ImageChange extends AsyncTask<Void, Void, Void> {
Activity act;
public ImageChange(Activity act) {
this.act = act;
}
protected void onPostExecute(Void unused) {
iv1.setImageBitmap(b1);
iv2.setImageBitmap(b2);
}
protected Void doInBackground(Void... arg0) {
switch(count) {
case 1:
helperMethod(f1.getAbsolutePath(), f2.getAbsolutePath());
break;
case 2:
helperMethod(f2.getAbsolutePath(), f1.getAbsolutePath());
break;
default :
count = 0;
helperMethod(f1.getAbsolutePath(), f2.getAbsolutePath());
break;
}
return null;
}
private void helperMethod(String a, String b) {
act.runOnUIThread(new Runable() {
public void run() {
b1 = BitmapFactory.decodeFile(a);
b2 = BitmapFactory.decodeFile(b);
}
});
}
}
Note that you must pass an Activity to the ImageChange class constructor. It means that you have to call the asyncTask in this way:
new ImageChange(this).execute();
Also consider the possibility of using the class TimerTask
EDIT: Change the Activity part of your code with this:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
.................
new ImageChange().execute();
} // OnCreate End
And add the while(true)
to the ImageChange class:
protected Void doInBackground(Void... arg0) {
while(true) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
count = count + 1;
switch(count) {
...
}
}
return null;
}
EDIT2: You can solve the problem about onPostExecute inserting the code that must be execute after each iteration inside the while loop:
protected Void doInBackground(Void... arg0) {
while(true) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
count = count + 1;
switch(count) {
...
}
act.runOnUIThread(new Runnable() {
public void run() {
iv1.setImageBitmap(b1);
iv2.setImageBitmap(b2);
}
});
}
return null;
}
The code you insert inside the while loop must run in the UI thread; in fact, every onPostExecute method of the AsyncTask class runs on UI thread.
Upvotes: 0
Reputation: 31463
You're calling the AsyncTask from a worker Thread. This way it has no access to the UI thread. You probably should consider using a Handler.
Upvotes: 1