0

我有一个 AsyncTask 子类的活动。执行异步任务后,我会丢失所有变量。我在调试模式下单步执行我的代码。一旦“MyAsync().execute()”完成,“formatedURL”变量(以及所有其他变量)就没有值了。在此之前,它们具有正确的值。然后,由于某种奇怪的原因,他们失去了价值观。我是在犯一个简单的 OO 错误,还是垃圾收集在做我不知道的事情。

public class NearbyList extends Activity {

    double lat;
    double lng;
    String restName;
    GPSHandling gps;
    String formatedURL;
    JSONObject jobject;
    ArrayList<HashMap<String, String>> listOfHM;
    ArrayList<String> listOfValues;
    String currentName;
    ListView lv;
    Context context;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.nearby_places_list);

        context = getApplicationContext();
        gps = new GPSHandling(this);
        lat = gps.getMyLatitude();
        lng = gps.getMyLongitude();
        restName ="";
        formatedURL = GooglePlacesStuff.placesURL(lat, lng, 16000, "food", restName, true);  //make a proper url. next step is to get a JSON object from this.


        new MyAsync().execute();// in order to run networking it must not be done in the UIthread. I use async task to take care of this in order to 
           //reduce the code of doing complex threading since this is a simple calculation
    }
        class MyAsync extends AsyncTask<Void, Integer, Boolean>{
            @Override
            protected Boolean doInBackground(Void... params) {
                try {
                    jobject = GooglePlacesStuff.getTheJSON(formatedURL);
                    listOfHM = JSONextractor.getJSONHMArrayL(jobject);
                    // iterate through and get the names of the nearby restaurants from the array of hasmap strings
                    for(int i =0 ; i < listOfHM.size() ;i++ ){
                        currentName = listOfHM.get(i).get(JSONextractor.TAG_NAME);
                        listOfValues.add(currentName);
                    }
                    return true;
                } catch (Exception e){
                    Log.e("Nearby List Activity", "exception", e);
                    return false;}
            }

            @Override
            protected void onPostExecute(Boolean result){
                super.onPostExecute(result);
                if (result){
                    ListAdapter adapter = new SimpleAdapter(context, listOfHM, R.layout.nearby_places_list, new String[]{JSONextractor.TAG_NAME,
                            JSONextractor.TAG_VICINITY, JSONextractor.TAG_GEO_LOC_LAT}, new int[]{ R.id.name, R.id.vicinity, R.id.phone});

                    // adding data to listview
                    lv.setAdapter(adapter);
                } else{
                    Toast.makeText(getApplicationContext(), "Need Internet & GPS access for this to work", Toast.LENGTH_LONG).show();
                }
                gps.stopUsingGPS();  // stop using the gps after i get the list to save on resource
            }
        }
}

Edit1:看起来它正在尝试在 doinbackground() 方法中多次运行“super.onCreate(Bundle savedInstanceState)”

Edit2:如果我将值设为静态,它们就不会丢失。很奇怪,即使是在异步任务中分配的变量“jobject”也不会接受分配,除非它是一个静态变量......从来没有见过这样的事情

4

3 回答 3

2

当您说它们没有值时,您是在 AsyncTask 中检查它们吗?如果是这样,这可能是原因(来自AsyncTask):

内存可观察性

AsyncTask 保证所有回调调用都以这样一种方式同步,即以下操作在没有显式同步的情况下是安全的。

  • 在构造函数或 onPreExecute() 中设置成员字段,并在 doInBackground(Params...) 中引用它们。
  • 在 doInBackground(Params...) 中设置成员字段,并在 onProgressUpdate(Progress...) 和 onPostExecute(Result) 中引用它们。

基本上,您不应该从 doInBackground() 访问您的实例变量,因为它不是线程安全的。就像函数说的那样,它在一个单独的(后台)线程中运行。您可以通过使它们成为静态(您尝试过)或同步它们来解决它,但最好按照预期的方式使用 AsyncTask 。

所以我认为你应该做到以下几点:

  1. 将 formatedURL 作为参数传递给 AsyncTask

  2. 从 doInBackground() (listOfHM) 返回 ArrayList<HashMap<String, String>>

  3. 在 onPostExecute() 中使用传入的 ArrayList<HashMap<String, String>>

  4. 我还将在 onCreate 中另外设置 ListAdapter,并仅更新支持 ListAdapter onPostExecute() 的数据。但我不会在这里讨论这个问题,因为这可能是一个单独的问题。这个是可选的。

代码:

class MyAsync extends AsyncTask<String, Integer, ArrayList<HashMap<String, String>>> {
    @Override
    protected ArrayList<HashMap<String, String>> doInBackground(String... urls) {
        ArrayList<HashMap<String, String>> listOfHM = null;
        if (urls != null && urls.length > 0 && urls[0] != null) {
            String formattedUrl = urls[0];
            try {
                JSONObject jobject = GooglePlacesStuff.getTheJSON(formattedURL);
                listOfHM = JSONextractor.getJSONHMArrayL(jobject);
            } catch (Exception e) {
                // log error
            }
        }
        return listOfHM;
    }

    @Override
    protected void onPostExecute(ArrayList<HashMap<String, String>> listOfHM){
        if (listOfHM != null && !listOfHM.isEmpty()) {
            // iterate through and get the names of the nearby restaurants from the array of hasmap strings
            for(int i =0 ; i < listOfHM.size() ;i++ ){
                String currentName = listOfHM.get(i).get(JSONextractor.TAG_NAME);
                listOfValues.add(currentName);
            }
            // do your adapter stuff
        }
        gps.stopUsingGPS();  // stop using the gps after i get the list to save on resource
    }
}

在你的 onCreate() 你会做

new MyAsync(formattedUrl).execute();

希望能帮助到你!

于 2012-10-24T18:29:29.023 回答
0

尝试分离功能和职责,在你的异步类中创建一个构造函数并将活动作为参数传递,就像在线程中维护上下文以避免任何内存泄漏一样,在活动中定义一些函数来完成后执行任务数据只是“活”在活动中(定义适配器,将适配器分配给列表视图,停止 gps 使用等),在 onpostexecute 中只需调用 mActiviy.doAfterTaskFinish()。关键是分开责任,这可以帮助您找到问题所在。

于 2012-10-24T18:29:22.023 回答
0

事实证明,我问了一个关于我的应用程序中实际上没有发生的事情的问题。显然,当您使用 Async Task 类时,on create 方法中的所有变量以及 onPostExecute() 和 doInBackground() 中的所有变量(文件中的几乎所有变量)都不会显示值(除非您使它们成为静态的),即使它们在您逐步执行这些方法时确实具有值。我不知道为什么会这样。我只是太依赖使用调试器来检查我的变量是什么。对困惑感到抱歉。

于 2012-10-24T22:10:41.450 回答