Вопрос по java, android – Java Не могу создать обработчик внутри потока, который не вызвал Looper.prepare ()

3

Я видел большинство связанных вопросов, но не смог найти ни одного, который бы решал мою проблему.

Это мой код, и я понятия не имею, что я делаю неправильно.

static class NamedFile {
    public File f;

    public String name;
    public String ext;
    public String path;
    public BitmapDrawable icon;

    public NamedFile (File file) {
        f = file;
        name = f.getName();
        if (f.isFile()) {
            if (name.indexOf('.') != -1) {
                ext = name.substring(name.lastIndexOf('.') + 1).trim().toLowerCase();
            } else {
                ext = "unknown";
            }
        }
        path = f.getAbsolutePath();

        if (ext == null) {
            icon = mFolderIcon;
        } else {
            BitmapDrawable i = icons.get(ext);
            if (i == null) {
                    try {
                        int rid = R.drawable.class.getField(ext).getInt(R.drawable.class);
                        icons.put(ext, new BitmapDrawable(Bitmap.createScaledBitmap(BitmapFactory.decodeResource(res, rid, mOpts), iconSize, iconSize, false)));
                        icon = icons.get(ext);
                    } catch (Exception e1) {}
            } else {
                icon = i;
            }
        }/* else if (ext.equals("jpeg") || ext.equals("jpg") || ext.equals("bmp") || ext.equals("gif") || ext.equals("png")) {
            Bitmap b = BitmapFactory.decodeFile(path, mOpts);
            if (b != null) {
                icon = new BitmapDrawable(Bitmap.createScaledBitmap(b, iconSize, iconSize, false));
            }
        }*/

        if (ext != null && (ext.equals("jpeg") || ext.equals("jpg") || ext.equals("bmp") || ext.equals("gif") || ext.equals("png"))) {
            /*
            Bitmap b = BitmapFactory.decodeFile(path, mOpts);
            if (b != null) {
                icon = new BitmapDrawable(Bitmap.createScaledBitmap(b, iconSize, iconSize, false));
            }
            */

            final Handler handler = new Handler() {
                @Override
                public void handleMessage(Message message) {
                    HashMap<String, Object> m = ((HashMap<String, Object>)message.obj);
                    sendThumbnail ((String)m.get("path"), (byte[])m.get("data"));
                }
            };


            Thread thread = new Thread() {
                public void writeInt (byte[] buff, int pos, int value) {
                    buff[pos] = (byte)(value >>> 24);
                    buff[pos + 1] = (byte)(value >>> 16);
                    buff[pos + 2] = (byte)(value >>> 8);
                    buff[pos + 3] = (byte)value;
                }

                @Override
                public void run() {
                    try {
                        Bitmap b = BitmapFactory.decodeFile(path, mOpts);
                        if (b.getHeight() > 256 || b.getWidth() > 256) {
                            float r;
                            if (b.getHeight() > b.getWidth()) {
                                r = 128f / b.getHeight();
                            } else {
                                r = 128f / b.getWidth();
                            }

                            b = Bitmap.createScaledBitmap(b, (int)(r * b.getWidth()), (int)(r * b.getHeight()), false);

                            byte[] buffer = new byte[b.getWidth() * b.getHeight() * 4 + 8];

                            writeInt (buffer, 0, b.getWidth());
                            writeInt (buffer, 4, b.getHeight());

                            int i = 8;
                            for (int y = 0; y < b.getHeight(); y ++) {
                                for (int x = 0; x < b.getWidth(); x ++) {
                                    writeInt (buffer, i, b.getPixel(x, y));

                                    i += 4;
                                }
                            }

                            HashMap<String, Object> msg = new HashMap<String, Object>();

                            msg.put("path", path);
                            msg.put("data", buffer);

                            Message message = handler.obtainMessage(1, msg);
                            handler.sendMessage(message);
                        }
                    } catch (Exception e) {
                        sendLog (e.toString());
                    }
                }
            };
            thread.start();


        }

        if (icon == null) {
            icon = mFileIcon;
        }
    }
    public NamedFile () {
    }

    public NamedFile simpleClone () {
        final NamedFile nf = new NamedFile();

        nf.name = name;
        nf.ext = ext;
        nf.path = path;

        return nf;
    }
}

Это вложено в оператор if, который находится в статическом классе & apos; Функция конструктора и статический класс находятся в публичном классе, который расширяет ListActivity. Я новичок в Java.

Ошибка:

05-01 20:21:58.810: E/AndroidRuntime(584): Uncaught handler: thread AsyncTask #1 exiting due to uncaught exception
05-01 20:21:58.830: E/AndroidRuntime(584): java.lang.RuntimeException: An error occured while executing doInBackground()
05-01 20:21:58.830: E/AndroidRuntime(584):  at android.os.AsyncTask$3.done(AsyncTask.java:200)
05-01 20:21:58.830: E/AndroidRuntime(584):  at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
05-01 20:21:58.830: E/AndroidRuntime(584):  at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
05-01 20:21:58.830: E/AndroidRuntime(584):  at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
05-01 20:21:58.830: E/AndroidRuntime(584):  at java.util.concurrent.FutureTask.run(FutureTask.java:137)
05-01 20:21:58.830: E/AndroidRuntime(584):  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1068)
05-01 20:21:58.830: E/AndroidRuntime(584):  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:561)
05-01 20:21:58.830: E/AndroidRuntime(584):  at java.lang.Thread.run(Thread.java:1096)
05-01 20:21:58.830: E/AndroidRuntime(584): Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
05-01 20:21:58.830: E/AndroidRuntime(584):  at android.os.Handler.<init>(Handler.java:121)
05-01 20:21:58.830: E/AndroidRuntime(584):  at greg.projects.FileTransfer.FileTransferActivity$NamedFile$1.<init>(FileTransferActivity.java:588)
05-01 20:21:58.830: E/AndroidRuntime(584):  at greg.projects.FileTransfer.FileTransferActivity$NamedFile.<init>(FileTransferActivity.java:588)
05-01 20:21:58.830: E/AndroidRuntime(584):  at greg.projects.FileTransfer.FileTransferActivity$GesturesLoadTask.doInBackground(FileTransferActivity.java:489)
05-01 20:21:58.830: E/AndroidRuntime(584):  at greg.projects.FileTransfer.FileTransferActivity$GesturesLoadTask.doInBackground(FileTransferActivity.java:1)
05-01 20:21:58.830: E/AndroidRuntime(584):  at android.os.AsyncTask$2.call(AsyncTask.java:185)
05-01 20:21:58.830: E/AndroidRuntime(584):  at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
05-01 20:21:58.830: E/AndroidRuntime(584):  ... 4 more

(FileTransferActivity.java:588 isfinal Handler handler = new Handler() {)

Я добавил это к вопросу. 19greg96
Вы не поделились соответствующей частью кода. опубликовать код конструктораNamedFile вложенный вFileTransferActivity, Особенно около 588-й линииFileTransferActivity Boris Strandjev
Какую ошибку вы получаете? Charles
final Handler handler = new Handler() { это линия 588 19greg96

Ваш Ответ

3   ответа
9

Handler в основном это класс обратного вызова, который Android использует для асинхронного запуска кода, когда вы отправляете ему сообщения какой-либо формы. Для того, чтобыHandler чтобы получать и обрабатывать сообщения в отдельном потоке от потока пользовательского интерфейса, он должен держать поток открытым. Вот гдеLooper класс входит. Как в примере страницы, вызовLooper.prepare() на вершинеrun() метод, затем вызватьLooper.loop() внизу. Поток останется открытым, пока вы явно не уничтожите его. Чтобы уничтожитьLooper вы должны иметь метод в вашемThread класс, который вызываетLooper.getMyLooper().quit().

Пример класса потока будет выглядеть примерно так:

class LooperThread extends Thread {
  public Handler mHandler;
  private volatile Looper mMyLooper;

  public void run() {
    Looper.prepare();

    mHandler = new Handler() {
       public void handleMessage(Message msg) {
          // process incoming messages here
       }
    };

    mMyLooper = Looper.getMyLooper();

    Looper.loop();
  }

  public void killMe(){
     mMyLooper.quit();
  }
}

Запустите поток как обычно, создав новый объект.

LooperThread myLooperThread = new LooperThread();

Держите ссылку на это. Затем позвоните:

myLooperThread.killMe();

Всякий раз, когда вы хотите, чтобы нить умерла. Это обычно вonPause(), onStop(), или жеonDestroy() методы деятельности.

Обратите внимание, что нить такого родаwill stay open when the activity is closed so you must kill it before the user quits.

Спасибо за это миллион - полный спасатель
Вместо того, чтобы создавать свой собственный LoopThread, вы можете использовать фреймворки handleThread, который сделает все это за вас:developer.android.com/reference/android/os/HandlerThread.html
И как я могу отправить сообщение в основную ветку? Итак, как я могу назвать этот методsendThumbnail (path, buffer); который определен в классе FileTransferActivity как статический метод и ссылается на статическую переменную (также), определенную в классе FileTransferActivity? 19greg96
Обработчики обрабатывают сообщения в любом потоке, в котором они созданы. Если вы хотите, чтобы обработчик обрабатывал сообщения в основном потоке, создайте обработчик в основном потоке. Затем передать ему сообщения из цепочки.
1

поскольку он готовит петлитель для вас.

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

2

 ActivityName.runOnUiThread(new Runnable() {
 public void run()
    {
     //put your logic here
    }
 });

Похожие вопросы