在后台线程中进行的地理位置请求冻结了主线程

时间:2014-10-02 17:23:35

标签: android multithreading android-handler android-looper android-handlerthread

我的应用程序有以下工作流程:main活动有一个按钮,在单击后启动第二个活动。在第二个活动中有一个TextView,它显示位于指定地理位置的城市。为了找到这个城市,我向Geocoder提出了我在后台主题中提出的请求。

我的期望:第二个活动立即开始(几乎),当后台线程完成请求时,ui线程更新TextView内容。

会发生什么:Geocoder完成其工作时,第二个活动仅启动 。为了显而易见,我们可以关闭wi-fi并点击按钮 - 期望的五六秒,并且在消息告知Geocoder无法获得地理点出现在日志中之后,第二项活动启动。

我做错了什么?相关代码如下,完整的示例项目为on github

public class SecondActivity extends Activity implements Handler.Callback {
    private HandlerThread mHandlerThread = new HandlerThread("BackgroundThread");
    private Handler mUIHandler;
    private Handler mBackgroundHandler;

    private TextView mLocationView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);

        mLocationView = (TextView) findViewById(R.id.location_name);

        mUIHandler = new Handler(getMainLooper(), this);

        mHandlerThread.start();
        mBackgroundHandler = new Handler(mHandlerThread.getLooper()) {
            @Override
            public void handleMessage(Message msg) {
                if (msg.what == 0) {
                    final Geocoder geocoder = new Geocoder(SecondActivity.this);

                    try {
                        final List<Address> results = geocoder.getFromLocation(53.539316, 49.396494, 1);

                        if (results != null && !results.isEmpty()) {
                            mUIHandler.dispatchMessage(Message.obtain(mUIHandler, 1, results.get(0)));
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
    }

    @Override
    protected void onResume() {
        super.onResume();
        mBackgroundHandler.dispatchMessage(Message.obtain(mBackgroundHandler, 0));
    }

    @Override
    public boolean handleMessage(Message msg) {
        if (msg.what == 1) {
            mLocationView.setText("I live in " + ((Address) msg.obj).getLocality());
            return true;
        }

        return false;
    }
}

1 个答案:

答案 0 :(得分:1)

我同意CommonsWare,使用AsyncTask可以让您的生活更轻松。只需根据需要调整参数和返回类型,或将变量保存在全局范围内。

new AsyncTask<Void, Void, Void>()
    {
        @Override
        protected Void doInBackground(Void... params)
        {
            // Your Geolocation operation goes here
            return null;
        }

        @Override
        protected void onPostExecute(Void result)
        {

            super.onPostExecute(result);
            // This is called when your operation is completed
        }
    }.execute();