Java 执行异步任务后,变量会丢失数据

Java 执行异步任务后,变量会丢失数据,java,android,multithreading,garbage-collection,android-asynctask,Java,Android,Multithreading,Garbage Collection,Android Asynctask,我有一个包含AsyncTask子类的活动。执行异步任务后,我将丢失所有变量。我正在调试模式下逐步完成我的代码。一旦“MyAsync().execute()”完成,“formattedUrl”变量(以及所有其他变量)就没有值。在此之前,它们具有正确的值。然后,出于某种奇怪的原因,他们失去了价值。是我犯了一个简单的OO错误,还是垃圾收集做了一些我不知道的事情 public class NearbyList extends Activity { double lat; double

我有一个包含AsyncTask子类的活动。执行异步任务后,我将丢失所有变量。我正在调试模式下逐步完成我的代码。一旦“MyAsync().execute()”完成,“formattedUrl”变量(以及所有其他变量)就没有值。在此之前,它们具有正确的值。然后,出于某种奇怪的原因,他们失去了价值。是我犯了一个简单的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
            }
        }
}
public类NearbyList扩展活动{
双lat;
双液化天然气;
字符串restName;
全球定位系统;
字符串格式的URL;
JSONObject jobject;
ArrayList-listOfHM;
数组列表值;
字符串currentName;
ListView lv;
语境;
@凌驾
创建时的公共void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.nearned_places_list);
context=getApplicationContext();
全球定位系统=新的全球定位系统(本);
lat=gps.getMyLatitude();
lng=gps.getMyLongitute();
restName=“”;
formattedUrl=GooglePlacesStuff.placesURL(lat,lng,16000,“food”,restName,true);//创建正确的url。下一步是从该url获取JSON对象。
new MyAsync().execute();//为了运行网络,不能在UIthread中执行。我使用async任务来处理这个问题,以便
//减少执行复杂线程的代码,因为这是一个简单的计算
}
类MyAsync扩展了AsyncTask{
@凌驾
受保护的布尔doInBackground(Void…params){
试一试{
jobject=GooglePlacesStuff.getTheJSON(formatterl);
listOfHM=JSONextractor.getJSONHMArrayL(jobject);
//迭代并从hasmap字符串数组中获取附近餐馆的名称
对于(int i=0;i
编辑1: 看起来它试图在doinbackground()方法中多次运行“super.onCreate(Bundle savedInstanceState)”


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

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

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

记忆可观察性

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

  • 在构造函数或onPreExecute()中设置成员字段,并在doInBackground(Params…)中引用它们
  • 在doInBackground(参数…)中设置成员字段,并在onProgressUpdate(进度…)和onPostExecute(结果)中引用它们
基本上,您不应该从doInBackground()访问实例变量,因为它不是线程安全的。正如函数所说,它在一个单独的(后台)线程中运行。您可以通过使它们成为静态(您尝试过)或同步它们来解决这个问题,但是按照预期的方式使用AsyncTask可能更好

因此,我认为你应该做以下几点:

  • 将formatedURL作为参数传递给AsyncTask

  • 从doInBackground()返回ArrayList(listOfHM)

  • 在onPostExecute()中使用传入的ArrayList

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

  • 代码:


    希望有帮助

    结果是,我问了一个关于我的应用程序中没有实际发生的事情的问题。显然,当您使用Async Task类时,onCreate方法中的所有变量以及onPostExecute()和doInBackground()中的所有变量(几乎所有文件中的变量)都不会显示值(除非您将它们设置为静态),即使它们在您运行时确实有值
    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
        }
    }
    
    new MyAsync(formattedUrl).execute();