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() から ArrayList<HashMap<String, String>> を返す (listOfHM)

  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 に答える