Android无法执行setListAdapter()用户线程

时间:2010-05-29 09:49:11

标签: android

抱歉,我的上一个问题编写得不好。所以我删除了内容并重新构建了我的问题。

我喜欢@ChrisBunney回答我的问题,并在另一个帖子中处理图像。

以下是正确的代码

public class TestActivity extends ListActivity {

    int count =0;

    List<String> listString = null;

    String[] mString = null; 

      private RefreshHandler mRedrawHandler = new RefreshHandler();

      class RefreshHandler extends Handler {

            @Override

            public void handleMessage(Message msg) {

                TestActivity.this.updateUI();

            }



            public void sleep(long delayMillis) {

              this.removeMessages(0);

              sendMessageDelayed(obtainMessage(0), delayMillis);

            }

          };



          private void updateUI(){



              mRedrawHandler.sleep(1000);

              listString.add("Test "+count++);

              String[] mString = new String[listString.size()];

              int i = 0;

              for(String string : listString){
                  mString[i++]= string;
              }

              if(null != mString && mString.length>0)
              setListAdapter(new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,mString ));


          }



          @Override 

          public void onCreate(Bundle icicle) { 

            super.onCreate(icicle); 

            setContentView(R.layout.main);

            listString = new LinkedList<String>();


            updateUI();


          } 



}

我打算做的是从另一个线程调用UI更新。

这将是我上面的代码文件的修改。

private class HelperClass implements Runnable{

            public void run() {

                performSomeCalculation();

            }

            /*
             * This code will populate the list as it is executed.
             * As and when there is a new element in the list the UI is updated.
             */

            public void performSomeCalculation(){

                //update list String
                updateUI();
            }

/*




/*
           * 
           * The new update onCreate method calling another thread that populates the UI thread
           * 
           */

          @Override 

          public void onCreate(Bundle icicle) { 

            super.onCreate(icicle); 

            setContentView(R.layout.main);

            listString = new LinkedList<String>();


            //updateUI();

            Thread thread = new Thread(new HelperClass());
            thread.start();


          }

你可以在上面的代码中看到我创建了一个HelperClass来执行一些计算,因为当计算线程输出时它应该更新UI线程。

我正在努力让它发挥作用,如果有人发现plz更新我的帖子。

提前致谢。

2 个答案:

答案 0 :(得分:0)

如果您想要更新UI的线程阻塞操作(例如从Internet下载图像),您应该使用Handler类来创建回调。

http://developer.android.com/reference/android/os/Handler.html

Handler类将绑定到UI线程,并允许您将实现Runnable接口的对象发布到队列中,以便在正确的线程中执行。

但是,我不确定是否有可能从给定的代码中实现您的目标。关于环境和期望行为的一些进一步信息将会有所帮助。

使用Handler更新UI的典型实现,基于我自己的应用程序中下载静态地图并更新UI的代码,可能如下所示:

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");
    }
}
}

答案 1 :(得分:0)

最后借助Chris的代码解决了我自己的问题。

Plz参考Chris的方法描述代码。

Plz纠正我的任何会议损失。

布局文件内容如下。

<ListView 
    android:id="@+id/list"         
    android:layout_span="1" 
    android:layout_width="324px" 
    android:layout_height="348px"/>

java文件内容如下。

import java.util.LinkedList;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.widget.ArrayAdapter;
import android.widget.ListView;


public class TestApp extends Activity {


    private final Handler handler = new Handler();

    private final UILoadingHelperClass uiLoadingThread = new UILoadingHelperClass();


    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.main);

        uiLoadingThread.setListView(R.id.list);

        new DataLoadingThread(handler, uiLoadingThread);        


    }


    private class DataLoadingThread extends Thread {

        int count = 0;

        LinkedList<String> linkedList = null;

        private final Handler handler;

        private final UILoadingHelperClass uiLoadingThread;


        public DataLoadingThread(Handler handler, UILoadingHelperClass uiLoadingThread) {
            this.handler = handler;
            this.uiLoadingThread = uiLoadingThread;
            this.start();
        }

        @Override
        public void run() {

            while(true){
                try {

                    Thread.sleep(1000);

                } catch (InterruptedException e) {

                    e.printStackTrace();

                }

                if(null == linkedList)
                    linkedList = new LinkedList<String>();

                linkedList.add("Test "+count++);

                int i=0;

                String[] strings = new String[linkedList.size()];

                for(String string : linkedList)
                    strings[i++]=string;

                uiLoadingThread.setSttrings(strings);

                handler.post(uiLoadingThread);
            }

        }
    }


    private class UILoadingHelperClass implements Runnable {

        private ListView listView = null;

        private String[] strings = null;

        public void setSttrings(String[] strings){
            this.strings = strings;
        }

        public void setListView(int id){
            listView = (ListView)findViewById(id);
        }

        public void run() {
            if(null != strings && strings.length>0)
                listView.setAdapter(new ArrayAdapter<String>(TestApp.this,android.R.layout.simple_list_item_1,strings));        

        }      
    }
}