过滤自动完成适配器的 json 个结果

Filter json results for Autocomplete adapter

我的应用程序有一个自动完成适配器,我正在从 Google 个地方 API 返回 json 结果。我的麻烦在于试图让结果显示在屏幕上。我正在使用本指南:http://examples.javacodegeeks.com/android/android-google-places-autocomplete-api-example/

在大多数情况下,代码似乎是正确的,但出于某种原因,我无法将任何内容打印到我的显示器上。我真的不明白过滤器是如何工作的,也许解释它如何与自动完成适配器一起工作会有所帮助。

我的 onCreate 是:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        buildGoogleApiClient();
        setContentView(R.layout.activity_maps);
        // Obtain the SupportMapFragment and get notified when the map is ready to be used.
        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);

        if (savedInstanceState != null) {
            mIsResolving = savedInstanceState.getBoolean(KEY_IS_RESOLVING);
            mShouldResolve = savedInstanceState.getBoolean(KEY_SHOULD_RESOLVE);
        }

//      Create the LocationRequest object
        mLocationRequest = LocationRequest.create()
                .setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY)
                .setInterval(10 * 1000)           //10 seconds, in milliseconds
                .setFastestInterval(1 * 1000);   //1 second, in milliseconds

        Log.d(TAG, "GoogleApiClient built");

        if (savedInstanceState != null) {
            mSignInProgress = savedInstanceState
                    .getInt(SAVED_PROGRESS, STATE_DEFAULT);
        }

        mShouldResolve = true;
        mGoogleApiClient.connect();
        Log.d(TAG, "Starting sign-in");



        AutoCompleteTextView autoCompView = (AutoCompleteTextView)
                findViewById(R.id.autoCompleteTextView);


        autoCompView.setAdapter(new GooglePlacesAutocompleteAdapter(this, R.layout.activity_maps));
        autoCompView.setOnItemClickListener(this);

    }

我获得 Json 结果的方法是:

public ArrayList<String> autocomplete(String input) {
        Log.d(TAG, "performSearch()");

        ArrayList resultList = null;

        AsyncTask<ArrayList<String>, Void, ArrayList>
                myTask = new AsyncTask<ArrayList<String>, Void, ArrayList>() {

            AutoCompleteTextView text = (AutoCompleteTextView)
                    findViewById(R.id.autoCompleteTextView);
            private String input = text.getText().toString();

            @Override
            protected ArrayList doInBackground(ArrayList<String>... params) {
                Log.d(TAG, "Starting Search");

                ArrayList resultList = null;

                HttpURLConnection conn = null;
                StringBuilder jsonResults = new StringBuilder();
                try {
                    KEYWORD = input;

                    ENDPOINT = Uri
                            .parse("https://maps.googleapis.com/maps/api/place/nearbysearch/json")
                            .buildUpon()
                            .appendQueryParameter("location", LOCATION)
                            .appendQueryParameter("radius", "10000")
                            .appendQueryParameter("keyword", KEYWORD)
                            .appendQueryParameter("key", API_KEY)
                            .build();

                    URL url = new URL(ENDPOINT.toString());

                    Log.d(TAG, "URL: " + url);

                    conn = (HttpURLConnection) url.openConnection();
                    InputStreamReader in = new InputStreamReader(conn.getInputStream());

                    // Load the results into a StringBuilder
                    int read;
                    char[] buff = new char[1024];
                    while ((read = in.read(buff)) != -1) {
                        jsonResults.append(buff, 0, read);
                    }
                    Log.d(TAG, jsonResults.toString());
                } catch (MalformedURLException e) {
                    Log.e(TAG, "Error processing Places API URL", e);
                    return resultList;
                } catch (IOException e) {
                    Log.e(TAG, "Error connecting to Places API", e);
                    return resultList;
                } finally {
                    if (conn != null) {
                        conn.disconnect();
                    }
                }
                try {
                    // Create a JSON object hierarchy from the results
                    JSONObject jsonObj = new JSONObject(jsonResults.toString());
                    JSONArray predsJsonArray = jsonObj.getJSONArray("results");

                    // Extract the Place descriptions from the results
                    resultList = new ArrayList(predsJsonArray.length());
                    for (int i = 0; i < predsJsonArray.length(); i++) {
                        System.out.println(predsJsonArray.getJSONObject(i).getString("name"));
                        System.out.println(predsJsonArray.getJSONObject(i).getString("vicinity"));
                        System.out.println("=====================================================");
                        resultList.add(predsJsonArray.getJSONObject(i).getString("name"));
                        resultList.add(predsJsonArray.getJSONObject(i).getString("vicinity"));
                    }
                } catch (JSONException e) {
                    Log.e(TAG, "Cannot process JSON results", e);
                }
                Log.d(TAG, resultList.toString());
                return resultList;
            }

        };

        myTask.execute();

        Log.d(TAG, resultList.toString());
        return resultList;
    }

我的过滤器 class 是:

class GooglePlacesAutocompleteAdapter extends ArrayAdapter implements Filterable {
        private ArrayList resultList;

        public GooglePlacesAutocompleteAdapter(Context context, int textViewResourceId) {
            super(context, textViewResourceId);
        }

        @Override
        public int getCount() {
            return resultList.size();
        }

        @Override
        public String getItem(int index) {
            return (String) resultList.get(index);
        }

        @Override
        public Filter getFilter() {
            Filter filter = new Filter() {
                @Override
                protected FilterResults performFiltering(CharSequence constraint) {
                    FilterResults filterResults = new FilterResults();
                    if (constraint != null) {
                        // Retrieve the autocomplete results.
                         resultList = autocomplete(constraint.toString());

                        // Assign the data to the FilterResults
                        filterResults.values = resultList;
                        filterResults.count = resultList.size();
                    }
                    return filterResults;
                }

                @Override
                protected void publishResults(CharSequence constraint, Filter.FilterResults results) {
                    if (results != null && results.count > 0) {
                        notifyDataSetChanged();
                    } else {
                        notifyDataSetInvalidated();
                    }
                }
            };
            return filter;
        }
    }

我知道我从 google 得到了一个声音结果,我构建的数组看起来像这样(它包括名称和附近):

[Midtown Global Market, 920 East Lake Street #G10, Minneapolis, The Anchor Fish & Chips, 302 13th Avenue Northeast, Minneapolis, Brasa Premium Rotisserie, 600 East Hennepin Avenue, Minneapolis, Wedge Community Co-Op, 2105 Lyndale Avenue South, Minneapolis, Tao Natural Foods, 2200 Hennepin Avenue, Minneapolis, Fresh & Natural Foods, 1075 Highway 96 West, Saint Paul, Whole Foods Market, 222 Hennepin Avenue, Minneapolis, Sen Yai Sen Lek Thai, 2422 Central Avenue Northeast, Minneapolis, Mississippi Market Natural Foods Co-op, 622 Selby Avenue, Saint Paul, Eastside Food Co-Op, 2551 Central Avenue Northeast, Minneapolis, Bills Imported Foods, 721 West Lake Street, Minneapolis, Seoul Foods, 1071 East Moore Lake Drive, Minneapolis, Seward Community Co-op - Franklin Store, 2823 East Franklin Avenue, Minneapolis, Foxy Falafel, 791 Raymond Avenue, Saint Paul, Asian Foods, 1300 L'Orient Street, Saint Paul, Pohl Distributing Co, 510 Kasota Avenue Southeast, Minneapolis, Rainbow Foods, 1566 University Avenue West, Saint Paul, Dandelion Kitchen Truck, 800 Nicollet Mall, Minneapolis, World Street Kitchen, 2743 Lyndale Avenue South #5, Minneapolis, CES Food Shelf, East 19th Street, Minneapolis]

感谢任何帮助,谢谢!

[编辑] 这是我的 XML activity_maps:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                 xmlns:tools="http://schemas.android.com/tools"
                 android:layout_width="match_parent"
                android:layout_height="match_parent"
                tools:context="com.hudsoncorp.zahudson.roadtrip.MapsActivity">

        <fragment xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:tools="http://schemas.android.com/tools"
            xmlns:map="http://schemas.android.com/apk/res-auto"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/map"
            tools:context="com.hudsoncorp.zahudson.roadtrip.MapsActivity"
            android:name="com.google.android.gms.maps.SupportMapFragment"/>

        <RelativeLayout
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:padding="10dp">

            <AutoCompleteTextView
                android:id="@+id/autoCompleteTextView"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:padding="10dp"
                android:hint="Search location"
                android:background="#FFFFFF"
                android:textColor="#00000F"
                      android:theme="@android:style/Widget.Material.AutoCompleteTextView"
                android:ems="10"
                android:shadowColor="@color/background_floating_material_dark">
                <requestFocus />

            </AutoCompleteTextView>

        </RelativeLayout>

</RelativeLayout>

我看到你有一个 AsyncTask 来从服务器访问你的数据,但你并不真的需要 AsyncTask 因为 performFiltering() 已经在后台运行,所以你可以将您的 doInBackground() 逻辑放入 performFiltering().

            @Override
            protected FilterResults performFiltering(CharSequence constraint) {

                ArrayList<String> resultList = null;
                FilterResults filterResults = new FilterResults();

                if (constraint != null) {
                    // Retrieve the autocomplete results.
                    Log.d(TAG, "Starting Search");

                    HttpURLConnection conn = null;
                    StringBuilder jsonResults = new StringBuilder();
                    try {
                        KEYWORD = constraint.toString();

                        ENDPOINT = Uri
                                .parse("https://maps.googleapis.com/maps/api/place/nearbysearch/json")
                                .buildUpon()
                                .appendQueryParameter("location", LOCATION)
                                .appendQueryParameter("radius", "10000")
                                .appendQueryParameter("keyword", KEYWORD)
                                .appendQueryParameter("key", API_KEY)
                                .build();

                        URL url = new URL(ENDPOINT.toString());

                        Log.d(TAG, "URL: " + url);

                        conn = (HttpURLConnection) url.openConnection();
                        InputStreamReader in = new InputStreamReader(conn.getInputStream());

                        // Load the results into a StringBuilder
                        int read;
                        char[] buff = new char[1024];
                        while ((read = in.read(buff)) != -1) {
                            jsonResults.append(buff, 0, read);
                        }
                        Log.d(TAG, jsonResults.toString());
                    } catch (MalformedURLException e) {
                        Log.e(TAG, "Error processing Places API URL", e);
                        return filterResults ;
                    } catch (IOException e) {
                        Log.e(TAG, "Error connecting to Places API", e);
                        return filterResults ;
                    } finally {
                        if (conn != null) {
                            conn.disconnect();
                        }
                    }
                    try {
                        // Create a JSON object hierarchy from the results
                        JSONObject jsonObj = new JSONObject(jsonResults.toString());
                        JSONArray predsJsonArray = jsonObj.getJSONArray("results");

                        // Extract the Place descriptions from the results
                        resultList = new ArrayList(predsJsonArray.length());
                        for (int i = 0; i < predsJsonArray.length(); i++) {
                            System.out.println(predsJsonArray.getJSONObject(i).getString("name"));
                            System.out.println(predsJsonArray.getJSONObject(i).getString("vicinity"));
                            System.out.println("=====================================================");
                            resultList.add(predsJsonArray.getJSONObject(i).getString("name"));
                            resultList.add(predsJsonArray.getJSONObject(i).getString("vicinity"));
                        }
                    } catch (JSONException e) {
                        Log.e(TAG, "Cannot process JSON results", e);
                    }
                    Log.d(TAG, resultList.toString());

                    // Assign the data to the FilterResults
                    filterResults.values = resultList;
                    filterResults.count = resultList.size();
                }
                return filterResults;
            }

A Filter 的工作方式类似于 AsyncTaskperformFiltering 类似于 doInBackgroundpublishResults() 类似于 onPostExecute()

顺便说一句,不要在后台线程中更新适配器列表。创建一个新列表并将其分配给 FilterResults.values,然后在 publishResults().

中分配适配器列表

publishResults() 应该是这样的:

            @Override
            protected void publishResults(CharSequence constraint, Filter.FilterResults results) {
                if (results != null && results.count > 0) {
                    resultList = (ArrayList) results.values;
                    notifyDataSetChanged();
                } else {
                    notifyDataSetInvalidated();
                }
            }