Если вы хотите выполнять операции блокировки потоков, которые обновляют пользовательский интерфейс (например, загрузка изображения из Интернета), вы должны использовать класс Handler
для создания обратного вызова.
http://developer.android.com/reference/android/os/Handler.html
Класс Handler
будет привязан к потоку пользовательского интерфейса и позволит вам размещать объекты, реализующие интерфейс Runnable
, в очередь для выполнения в правильном потоке.
Однако я не уверен, возможно ли достичь того, к чему вы, похоже, стремитесь, из данного кода. Некоторая дополнительная информация об обстоятельствах и желаемом поведении будет полезна.
Типичная реализация, использующая Handler
для обновления пользовательского интерфейса, основанная на коде из моего собственного приложения, которое загружает статическую карту и обновляет пользовательский интерфейс, может выглядеть следующим образом:
public class HandlerExample extends Activity {
/**
* Handler to allow other threads to send executable messages (in the form
* of Runnable objects) to the main UI thread. This is used to download the
* static image in a separate thread to stop the UI from blocking
*/
private final Handler handler = new Handler();
/**
* Runnable implementation that, in conjunction with handler, displays a
* given static map in the ImageView
*/
private final UpdateStaticMap updateStaticMap = new UpdateStaticMap();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//... other initialisation
// This object implements Runnable and is used to post our update to the Handler
updateStaticMap.setImageView((ImageView)findViewById(R.id.venuedetail_mapimage));
// Then we pass the Runnable object, the Handler, and all the data we
// need to get the
// map into a Thread subclass to avoid blocking the UI thread
// Note, the thread is started in the constructor so we don't worry about it here
new MapGetter(handler, updateStaticMap);
}
/**
* This private class extends Thread to handle the downloading of the static
* map separately from the main UI thread to avoid
* blocking it. It uses the Handler to trigger the UI thread to update the
* ImageView when it's finished by passing updateStaticMap as a message
* (it's a Runnable, thus will be executed by the handler in the UI thread).
* This is necessary as only the thread that created the View components can
* edit them.
*
* @author Chris Bunney
*
*/
private class MapGetter extends Thread {
/**
* The Handler associated with the UI thread. Used to pass the map back
* to the UI thread
*/
private final Handler handler;
/**
* The Runnable implementation used to wrap the bitmap when passing it
* back to the UI thread via handler
*/
private final UpdateStaticMap updateStaticMap;
/**
*
*
* @param handler
* Handler for the UI thread so the MapGetter can update the
* ImageView with the map
* @param updateStaticMap
* Runnable object that is used to send the map back to and
* update the UI
**/
public MapGetter(Handler handler, UpdateStaticMap updateStaticMap) {
this.handler = handler;
this.updateStaticMap = updateStaticMap;
this.start();
}
/**
* Obtains the Static Map and passes it back to the main
* UI thread to be displayed
*/
@Override
public void run() {
//Note, the getImage() method is just a stand in for whatever code you need to get the image
updateStaticMap.setBitmap(getImage()));
//Now our Runnable object has all the data it needs, we post it back to the Handler
handler.post(updateStaticMap);
}
}
/**
* This class implements the Runnable interface. It acts a message to be
* delivered to the UI thread. This class updates a given ImageView with a
* given Bitmap. The ImageView and Bitmap form the payload of the message.
* This class is necessary because only the thread that created a View can
* alter it, so the object is passed to the correct thread and executed by
* it.
*
* @author Chris Bunney
*
*/
private class UpdateStaticMap implements Runnable {
/**
* The ImageView to target when setting the bitmap
*/
private ImageView mapImage;
/**
* The Bitmap to update the ImageView with
*/
private Bitmap bm;
/**
* Inserts the Bitmap, bm, into the ImageView, mapImage
*
*/
@Override
public void run() {
mapImage.setImageBitmap(bm);
Log.d(TAG, "run: Static Map Updated");
}
/**
* Accessor method to insert the bitmap payload into the message
*
* @param bm
* Static map to be displayed in the UI
*/
public void setBitmap(Bitmap bm) {
this.bm = bm;
Log.d(TAG, "setBitmap: Bitmap updated");
}
/**
* Accessor method to associate the object with a particular ImageView
*
* @param mapImage
* ImageView that the map should be displayed in
*/
public void setImageView(ImageView mapImage) {
this.mapImage = mapImage;
Log.d(TAG, "setImageView: ImageView updated");
}
}
}