0

私は問題を抱えていて、問題がどこにあるのかを知っていますが、理解できないのは、なぜそれがうまくいくのか、他のときはうまくいかないのかということです. これが私がやりたいことです。

Google MapView を表示する Android アプリケーションがあり、この MapView の上にオートコンプリート テキストビューがあります。Google から (json 形式で) 値を取得し、このオートコンプリート テキストビューに表示できます。これは常に機能します。Google から取得したオプションの 1 つを押すと、その場所にズームしたいと思います。これはほとんどの場合機能します。

そのため、アドレス Elfde を押すと、Google から 5 つのオプション/予測が返されます。その後、それらのオプションを表示します。選択肢の 1 つは、ベルギーのエルフデ リニエ通りです。Google MapView がその場所にズームします。「ブレーメン」と入力してドイツのブレーメンを選択すると、その場所にズームします。しかし、Peer と入力してベルギーの Peer を選択すると、ArrayAdapter で indexOutOfBounds 例外が発生します。

今コード:

オートコンプリート TextView のテキストが変更されると、次のコードを使用します。

public void onTextChanged(CharSequence s, int start, int before,
                int count) {
            if (count % 3 == 1){                    
                // Get the places and pass the argument in the TextView to the task.
                GetPlaces task = new GetPlaces();
                task.execute(_txtFindLocation.getText().toString());
            }
        }       

アイテムをクリックすると、次のコードを使用します。

_txtFindLocation.setOnItemClickListener(new OnItemClickListener(){
        public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
                long arg3) {
            // Hide the keyboard.
            InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
            inputMethodManager.hideSoftInputFromWindow(_txtFindLocation.getWindowToken(), 0);

            Log.v("Take a look on variables", "item: " + String.valueOf(arg2) + ", AdapterView: " + arg0.getCount() + ", _strArrayAdapter: " + _strArrayAdapter.getCount());

            // Move to specified location.
            moveToLocation(arg0.getItemAtPosition(arg2).toString());

                    // Clear the adapter, to decrease the size.
            _strArrayAdapter.clear();
        }
    });

そして、ここで indexOutOfBoundsException が発生します。ベルギーの Elfde-Liniestraat の入力と選択の場合: arg2 = 0、arg0.getCount() = 5、_strArrayAdapter (ソースとして arg0 にリンクされている) = 5 ドイツのブレーメンの入力と選択の場合: arg2 = 3、 arg0.getCount() = 5、_strArrayAdapter = 5 Peer、ベルギー (エラーがスローされる場所) の入力と選択の場合: arg2 = 0、arg0.getCount() = 0、_strArrayAdapter = 0

したがって、間違いなくここでエラーがスローされます。_strArrayAdapter は、この関数で埋められます。

private class GetPlaces extends AsyncTask<String, Void, ArrayList<String>>{

    @Override
    protected ArrayList<String> doInBackground(String... params) {
        ArrayList<String> myPredictions = new ArrayList<String>();
        Log.d("Search places", "params: " + params[0].toString());
        try{
            URL myURL = new URL("https://maps.googleapis.com/maps/api/place/autocomplete/json?input="
                    + URLEncoder.encode(params[0], "UTF-8")
                    + "&types=geocode&language=en&sensor=true&key=API_KEY");
            URLConnection myURLConnection = myURL.openConnection();         
            BufferedReader myBufferReader = new BufferedReader(new InputStreamReader(myURLConnection.getInputStream()));

            String strLine;
            StringBuffer strBuffer = new StringBuffer();
            // Take Google's legible JSON and turn it into on big String.
            while((strLine = myBufferReader.readLine()) != null){
                strBuffer.append(strLine);
            }

            // Turn String into a JSON Object.
            JSONObject jsonPredictionsObject = new JSONObject(strBuffer.toString());
            // Get a JSON Array that is inside the JSON Object.
            JSONArray jsonPredictionsArray = new JSONArray(jsonPredictionsObject.getString("predictions"));

            for (int i = 0; i < jsonPredictionsArray.length(); i++){
                jsonPredictionsObject = (JSONObject) jsonPredictionsArray.get(i);
                myPredictions.add(jsonPredictionsObject.getString("description"));
            }
        }
        catch (IOException e){
            Log.e("Search places", "GetPlaces: doInBackGround", e);
        }
        catch (JSONException e){
            Log.e("Search places", "GetPlaces: doInBackGround", e);
        }

        return myPredictions;
    }

    protected void onPostExecute(ArrayList<String> result){
        Log.d("YourApp", "onPostExecute: " + result.size());

        // Update the adapter.
        _strArrayAdapter = new ArrayAdapter<String>(getBaseContext(), R.layout.activity_list_item);
        _strArrayAdapter.setNotifyOnChange(true);

        // Attach the adapter to the TextView.
        _txtFindLocation.setAdapter(_strArrayAdapter);

        for (String text : result){
            Log.d("Search places", "onPostExecute: result = " + text);

            _strArrayAdapter.add(text);
        }

            _strArrayAdapter.clear();

        Log.d("Search places", "onPostExecute: autoCompleteAdapter " + _strArrayAdapter.getCount());
    }

3 つのテストケースすべてについて、最後の Log.d("Search places", "onPostExecute: autoCompleteAdapter " + _strArrayAdapter.getCount()); 5の値を与えてください!

したがって、_strArrayAdapter はすべての場合に満たされますが、項目を選択すると、場合によっては _strArrayAdapter の値が 0 に設定されるため、満たされません。

なぜこうなった?

敬具 Martijn Haex

編集返信のおかげで、コード(上記)を少し見直しましたが、今では魅力的に機能します。

4

2 に答える 2

0

文字数が x*3+1 (1、4、7、10、...) の場合、結果をクリアしているようです。

        if (count % 3 == 1){
            _strArrayAdapter.clear();

3 文字以上の場所だけを検索したかったようですね。そうあるべき

        if (count > 3){
            _strArrayAdapter.clear();

また、postExecute で、アダプタに追加されたすべてのアイテムで notifyDataSetChanged() を呼び出していることがわかりました。少し最適化できます。実際、完全に削除できます。

protected void onPostExecute(ArrayList<String> result){
    Log.d("YourApp", "onPostExecute: " + result.size());

    // Update the adapter.
    _strArrayAdapter = new ArrayAdapter<String>(getBaseContext(), R.layout.activity_list_item);

    for (String text : result){
        Log.d("Search places", "onPostExecute: result = " + text);

        temp.add(text);
        _strArrayAdapter.add(text);
    }


    // Attach the adapter to the TextView.
    _txtFindLocation.setAdapter(_strArrayAdapter);

    Log.d("Search places", "onPostExecute: autoCompleteAdapter " + _strArrayAdapter.getCount());
}

また、例外が発生した場合は、コード内の行番号にもいくつかの参照を付けてスタックトレースをポストに入れて、問題を追跡しやすくします。

于 2012-10-31T09:44:56.320 に答える
0

問題は、関数の次のスニペットにあるようonTextChangedです。ところで、なぜ配列をクリアするのlengthOfModifiedText % 3 == 1ですか?:

if (count % 3 == 1){
                _strArrayAdapter.clear();

を入力する"Peer"と、配列がクリアされます (要素なし)。長さ のテキストを入力するたびに、コードに従ってクリアされますL, where L % 3 == 1strArrayAdapter

于 2012-10-31T09:22:59.640 に答える