0

我有一个AsyncTask子类的活动。一旦执行异步任务,我将失去所有的变量。我正在调试模式下遍历我的代码。只要“MyAsync()。execute()”完成“formaticURL”变量(以及所有其他变量)没有值。在此之前,他们有正确的价值观。然后,出于某种奇怪的原因,他们失去了价值。我是在做一个简单的面向对象程序错误还是在做垃圾收集,我不知道。执行Async Task任务后,变量会丢失数据

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()方法

EDIT2运行 “super.onCreate(包savedInstanceState)” 多次:如果我做的值静态他们不走开。它的奇怪,即使是异步任务内分配的变量“jobject”也不会采取任务,除非它的静态变量....从来没有见过类似的东西

+0

没有“没有价值”的可能性。 'null'仍然是一个值。你有什么价值? –

+0

它们是否具有您期望的onPostExecute结尾的值? – toadzky

+0

@ webnetMobile:当我查看它们没有设置为null的变量时,它看起来好像没有任何价值。通常,当它们为空时,它们会说“null” @taodzky:在doInBackground()和onpostexecute期间或之后仍未分配。 () –

回答

2

当你说他们没有价值时,你是否在AsyncTask中检查它们?如果是这样,这可能是(从AsyncTask)的原因:

内存可观测

的AsyncTask保证所有的回调调用以这样的方式,下面的操作是没有明确的同步安全同步。

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

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

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

  1. 作为参数传递到的AsyncTask

  2. 返回的ArrayList <的HashMap <字符串,字符串> >从doInBackground()(listOfHM )

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

  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(); 

希望它能帮助!

+0

或者,您也可以传递JSONObject而不是HashMap的ArrayList,并在onPostExecute中执行json解析 – hiBrianLee

+0

感谢您的信息。我认为你的答案应该有效,即将尝试。现在关于你的“第4步”答案:为什么我会在创建方法中设置listAdapter,因为它将所有赋值都丢失到类似变量中? –

+0

通常对于带游标的数据库备份适配器,您可以为您的listview设置适配器一次,并且每当备份数据发生更改时,listview会自动更新,而不必在每次数据更改时都通过光标通知重新设置适配器。但在你的情况下,你只是使用一个带有静态数据的SimpleAdapter,所以它并不重要,所以你可以忽略我说的=) – hiBrianLee

0

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

0

事实证明,我问了一个关于在我的应用程序中没有实际发生的事情的问题。显然,当你使用异步任务类时,on方法和onPostExecute()和doInBackground()中的所有变量(文件内几乎所有的变量)都不会显示一个值(除非你使他们静态),即使他们实际上确实有价值,而你正在通过这些方法。我不知道这是为什么。我太依赖于使用调试器来检查我的变量是什么。对困惑感到抱歉。