【问题标题】:Creating threads from Activity.onCreate() that never die从 Activity.onCreate() 创建永不消亡的线程
【发布时间】:2011-10-25 22:09:57
【问题描述】:

我花了几个小时在这里寻找答案,但似乎没有什么让我明白。

这是我的问题:我有一个带有主菜单的简单应用。其中一个选项从 PHP 服务器检索 cmets 列表,更新数据库,然后显示 ListView。

内部一切正常。现在,每次我按回然后再次启动活动时,都会启动一个新线程。我设法达到了 50 多个等待线程。我正在使用 Eclipse 中的 DDMS 选项卡来监控胎面。

如果我尝试调用 Looper.getLooper().quit()Looper.myLooper().quit(),我会收到一条错误消息“不允许退出主线程”。

我做错了什么,我应该在哪里/如何停止线程?

代码如下:

public class RequestActivity extends Activity {

    ProgressDialog pDialog;
    DatabaseHelper db;
    int userId;
    myCursorAdapter adapter;
    Thread runner = null;
    ListView list;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        userId = myApplication.getInstance().getSession().getUserId();
        setContentView(R.layout.request_list);

        db = new myProvider.DatabaseHelper(this);
        Cursor cursor = db.getRequests(userId);
        startManagingCursor(cursor);
        adapter = new myCursorAdapter(RequestActivity.this, cursor);
        list = (ListView) findViewById(R.id.list);
        list.setVisibility(View.INVISIBLE);
        list.setAdapter(adapter);

        pDialog = ProgressDialog.show(RequestActivity.this, "", "Loading ...", true, false);

        runner = new Thread() {
            Handler handler = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    adapter.getCursor().requery(); 
                }
            };  

            public void run() {
                Looper.prepare();
                // ... setup HttpGet
                try {
                    // ... get HTTP GET response 
                    if (response != null) {
                        // ... update database
                        handler.sendEmptyMessage(0);
                    }
                } catch(Exception e) {
                    // .. log exception
                }
                Looper.loop();
            }
        };
        runner.start();
    }

    private static class ViewHolder {
        // .. view objects
    }

    private class myCursorAdapter extends CursorAdapter {
        private LayoutInflater inflater;
        public myCursorAdapter(Context context, Cursor c) {
            super(context, c);
            inflater = LayoutInflater.from(context);
        }

        @Override
        public void bindView(View view, Context context, Cursor cursor) {
            // .. bind data
            if (cursor.isLast()) {
                pDialog.dismiss();
                list.setVisibility(View.VISIBLE);
            }
        }

        @Override
        public View newView(Context context, Cursor cursor, ViewGroup parent) {
            View view = inflater.inflate(R.layout.request_list_item, parent, false);
            ViewHolder holder = new ViewHolder();
            // .. set holder View objects
            view.setTag(holder);
            return view;
        }
    }

}

【问题讨论】:

    标签: android multithreading thread-safety


    【解决方案1】:

    您正在主线程的 Looper 上调用 quit()。不是线程的 Looper。

    你可以试试这个。创建一个扩展 Thread 的单独私有内部类。在 run() 方法中,调用 Looper.myLooper() 以将线程的 Looper 实例保存在类中。然后有一个退出方法,在该循环器上调用退出。

    例子:

    private class LooperThread extends Thread{
       private Looper threadLooper;
    
       @Override
       public void run(){
          Looper.prepare();
          threadLooper = Looper.myLooper();
          Looper.loop();
       }
    
       public void stopLooper(){
          if(threadLooper != null)
              threadLooper.quit();
       }
    }
    

    【讨论】:

    • 就是这样!我知道你不能在活动的Looper 上调用quit(),但我从未想过要获得thread looper inisde run()。再次感谢!
    【解决方案2】:

    在您的 onDestroy 方法中,您是否会调用任何方法来停止线程?

    public void onDestroy()
    {
        Thread moribund = runner;
        runner = null
        moribund.interrupt();
    
    }
    

    【讨论】:

    • Jack 我已经这样做了,但是线程还活着,并且 isInterrupted() 返回 false。
    • 我要做的其他事情是在我的 Thread 类中添加一个 requestedStop 布尔值。并创建一个 requestStop() 方法将其设置为 true。我在我的循环中添加了一个条件,它说只有 continue IF !requestedStop
    • 谢谢,我搞定了。问题是我在 Activity 中调用 Looper.myLooper()not 在 Thread 中。我学会了艰难的方式:)
    【解决方案3】:

    您在主 (UI) 线程中调用 Looper.quit() 方法,这是不允许的。尝试将Runnable 发布到调用Looper.quit() 的线程内的处理程序。这将导致线程上下文中的Looper 退出。

    【讨论】:

      猜你喜欢
      • 2011-03-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-10-07
      • 1970-01-01
      相关资源
      最近更新 更多