0

Web サービスからデータを取り込むアプリがありArrayListます。Web サービスは から呼び出されますAsyncTask。でテストすると、ArrayList にデータが入力されonPostExecuteます。ArrayList はインスタンス変数として定義されます。AsyncTask が終了すると、arrayList が入力されますが、後でインスタンス変数自体をテストすると、null になるのはなぜですか。Async が値を適切に設定していないようです。

Async が終了したら、ArrayList を arrayAdapter に渡しますが、listView は空です。

テスト: でonPostExecute

 Log.e(TAG, "array from WS = " + array.size());  // returns 4

テスト: でonCreate

 Log.e(TAG, "checking to see if array is null " + array.size()); // returns 0



 package com.carefreegroup;

 public class GetRotaDetails extends NfcBaseActivity implements OnItemClickListener
 {
ArrayList<ArrayList<String>> array;
MySimpleArrayAdapter arrayAdapter;
Intent intent;
private static final String TAG = GetRotaDetails.class.getSimpleName();
ListView listView;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    array = new  ArrayList<ArrayList<String>>();
    nfcscannerapplication = (NfcScannerApplication) getApplication();
    intent = this.getIntent();
    setContentView(R.layout.getrotadetailslayout);
    listView = (ListView) findViewById(R.id.getrotadetailslistview);

    //set titlebar to carer's name
    Cursor cursorCarerName = nfcscannerapplication.loginValidate.queryAllFromCarer();
    cursorCarerName.moveToLast();
    String carerTitleName = cursorCarerName.getString(cursorCarerName
            .getColumnIndex(LoginValidate.C_CARER_NAME));
    setTitle(carerTitleName + " is currently logged in");

    callID = intent.getStringExtra("callIDExtra");
    Log.e(TAG, "callID = " + callID);
    String[] params = { callID };
    AsyncGetRotaDetails agrd = new AsyncGetRotaDetails();
    agrd.execute(params);

    Log.e(TAG, "checking to see if array is null " + array.size());
    if (arrayAdapter == null){
        MySimpleArrayAdapter arrayAdapter = new MySimpleArrayAdapter(this, array);
        listView.setAdapter(arrayAdapter);
    }
    listView.setAdapter(arrayAdapter);
    listView.setOnItemClickListener(this);


}// end of onCreate

@Override
protected void onResume() {


    super.onResume();
}


private class AsyncGetRotaDetails extends AsyncTask<String, Void, String> {

    ProgressDialog progressDialog;
    String rotaDetails = null;

    @Override
    protected void onPreExecute() {
        progressDialog = ProgressDialog
                .show(GetRotaDetails.this, "Connecting to Server",
                        " retrieving rota details...", true);

    };

    @Override
    protected String doInBackground(String... params) { 

        try {
            Log.e(TAG, "inside doInBackground");

            rotaDetails = nfcscannerapplication.loginWebservice.getRotaDetail(params[0]);

        } catch (Exception e) {

            e.printStackTrace();

        }
        return rotaDetails;

    }

    @Override
    protected void onPostExecute(String xmlResult) {
        super.onPostExecute(xmlResult);
        if (progressDialog != null)
            progressDialog.dismiss();

        if (rotaDetails != null) {



            RetrieveExtraDetails red = new RetrieveExtraDetails();
           array = red.getExtraDetails(xmlResult);
            Log.e(TAG, "array from WS = " + array.size());

        } else {

            AlertDialog alertDialog = new AlertDialog.Builder(
                    GetRotaDetails.this).create();
            alertDialog.setTitle("Signal/Server Test");
            alertDialog.setMessage("No Phone Signal or Server Problem");

            alertDialog.setButton("OK",
                    new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog,
                                int which) {

                            onStart();
                        }
                    });

            alertDialog.show();

        }

    }// end of postExecute

}//end of Async

private class MySimpleArrayAdapter extends ArrayAdapter<String> {



    private final Context context;
    private final ArrayList<?> list;

    public MySimpleArrayAdapter(Context context, ArrayList<?> list) {

        super(context, R.layout.getrotadetailsrow);
        Log.e(TAG, "inside adapter constructor");
        this.context = context;
        this.list = list;


    }// end of constructor

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        LayoutInflater inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        View rowView = inflater.inflate(R.layout.getrotadetailsrow, parent,
                false);

        TextView recTypeID = (TextView) rowView
                .findViewById(R.id.rectypeid);

        TextView recType = (TextView) rowView
                .findViewById(R.id.rectype);

        TextView name = (TextView) rowView
                .findViewById(R.id.name);

        TextView relationship = (TextView) rowView
                .findViewById(R.id.relationship);

        TextView address = (TextView) rowView
                .findViewById(R.id.address);

        TextView postCode = (TextView) rowView
                .findViewById(R.id.postcode);

        TextView telNo = (TextView) rowView
                .findViewById(R.id.telno);

        TextView keySafe = (TextView) rowView
                .findViewById(R.id.keysafe);

        TextView notes = (TextView) rowView
                .findViewById(R.id.notes);

        TextView meds = (TextView) rowView
                .findViewById(R.id.meds);

        String record = list.get(position).toString();

        Log.e(TAG, "record = " + record);
        recTypeID.setText(record);
        return super.getView(position, convertView, parent);
    }

}

@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
    // TODO Auto-generated method stub

}

}
4

2 に答える 2

2

実際には、AsyncTask は非同期で実行されます。これは、ブロッキング呼び出しではありません ( onPostExecute() の実行後に execute() メソッドが戻るなど)。そのため、データがダウンロードされたときに onPostExecute() でアダプターに通知する必要があります。マルチスレッド関連の問題です。execute() 行が実行されると、AsyncTask のスレッドが作成され、onCreate() の実行が次の行に移動するため、同時に doInBackground() と onCreate() が AsyncTask スレッドと UI で実行されます。それぞれスレッド。

于 2012-10-09T13:33:16.057 に答える
0

ListView をクラスのフィールドにして、

使用する

listView.setAdapter(arrayAdapter);
listView.setOnItemClickListener(this);

onPostExecute(String result)メソッドで

しかし、私が推奨するのは次のとおりです。

データがフェッチされ、アダプターが設定されるまでローディング スピナーを使用します。そうしないと、アクティビティが空として表示され、3 ~ 5 秒後に突然リスト全体が表示されるという動作が発生します。これは悪い UX です。

通常、フェッチされるデータが UI の主要なコンポーネントである ListView ではなく、UI の小さな部分である場合は、ロード スピナーを使用せずに非同期タスクを使用します。

onCreate() で配列の長さをチェックしないでください。コードフローは次のようになるため、常に0になります。

1.配列を作成する

2. まだ何も追加されていないため、onCreate //0 で長さを確認します

3.バックグラウンドで配列にデータを追加する

4. onPostExecute(String result) でその長さを確認します //実際の長さ

于 2012-10-09T14:03:28.677 に答える