如何在doInBackground方法中执行gui操作?

时间:2012-10-21 22:56:56

标签: android user-interface android-asynctask

我的应用程序读取包含地址的用户所选文件,然后在完成地理编码时显示在mapview上。为避免挂起应用程序,导入和地理编码在AsyncTask中完成。

public class LoadOverlayAsync extends AsyncTask<Uri, Integer, StopsOverlay> {

    Context context;
    MapView mapView;
    Drawable drawable;

    public LoadOverlayAsync(Context con, MapView mv, Drawable dw)
    {
        context = con;
        mapView = mv;
        drawable = dw;
    }

    protected StopsOverlay doInBackground(Uri... uris)
    {
        StringBuilder text = new StringBuilder();
        StopsOverlay stopsOverlay = new StopsOverlay(drawable, context);
        Geocoder geo = new Geocoder(context, Locale.US);

        try
        {   
            File file = new File(new URI(uris[0].toString()));

            BufferedReader br = new BufferedReader(new FileReader(file));
            String line;

            while ((line = br.readLine()) != null)
            {
                StopOverlay stopOverlay = null;
                String[] tempLine = line.split("~");
                List<Address> results = geo.getFromLocationName(tempLine[4] + " " + tempLine[5] + " " + tempLine[7] + " " + tempLine[8], 10);

                if (results.size() > 0)
                {
                    Toast progressToast = Toast.makeText(context, "More than one yo", 1000);
                    progressToast.show();
                }
                else if (results.size() == 1)
                {
                    Address addr = results.get(0);
                    GeoPoint mPoint = new GeoPoint((int)(addr.getLatitude() * 1E6), (int)(addr.getLongitude() * 1E6));
                    stopOverlay = new StopOverlay(mPoint, tempLine);
                }

                if (stopOverlay != null)
                {
                    stopsOverlay.addOverlay(stopOverlay);
                }
                //List<Address> results = geo.getFromLocationName(locationName, maxResults)

            }

        } catch (URISyntaxException e) {
            showErrorToast(e.toString());
            //e.printStackTrace();
        } catch (FileNotFoundException e) {
            showErrorToast(e.toString());
            //e.printStackTrace();
        } catch (IOException e) {
            showErrorToast(e.toString());
            //e.printStackTrace();
        }
        return stopsOverlay;
    }

    protected void onProgressUpdate(Integer... progress)
    {
        Toast progressToast = Toast.makeText(context, "Loaded " + progress.toString(), 1000);
        progressToast.show();
    }

    protected void onPostExecute(StopsOverlay so)
    {
        //mapView.getOverlays().add(so);
        Toast progressToast = Toast.makeText(context, "Done geocoding", 1000);
        progressToast.show();
    }

    protected void showErrorToast(String msg)
    {
        Toast Newtoast = Toast.makeText(context, msg, 10000);
        Newtoast.show();
    }
}

但是如果地理编码失败,我想要一个对话框弹出窗口让用户编辑地址。这需要在doInBackground中调用gui方法。这会是一个好的解决方法吗?

2 个答案:

答案 0 :(得分:0)

您必须在onPostExecute方法中处理它。也许设计它所以onPostExecute的null参数表明它失败了,所以在这种情况下弹出对话框。

答案 1 :(得分:0)

如果您不想更改StopsOverlay的Result类型,那么您可以做的是在doInBackground中设置一些成员字段,然后检查onPostExecute中的那些成员字段并在那时显示您的错误UI。

请注意,这是安全的,建议按AsyncTask docs

  

AsyncTask保证所有回调调用的同步方式使得以下操作在没有显式同步的情况下是安全的。

     

在doInBackground(Params ...)中设置成员字段,并在onProgressUpdate(Progress ...)和onPostExecute(Result)中引用它们。

例如,您可以声明一个字段:

private boolean mTooManyResults = false;

然后更改它,以便在doInBackground中,您有以下代码:

if (results.size() > 0)
{
    mTooManyResults = true;
}

然后在onPostExecute

if (mTooManyResults)
{
    // notify user about error
    Toast progressToast = Toast.makeText(context, "More than one yo", 1000);
    progressToast.show();
} else
{
    // notify user about success
    Toast progressToast = Toast.makeText(context, "Done geocoding", 1000);
    progressToast.show();
}