我正在尝试从PHP返回的数据中以JSON格式填充AutoCompleteTextView的应用程序。该应用程序可以编译,但是我似乎无法弄清问题所在。问题是Volley是异步的,我不知道在加载建议之前如何等待响应。
在相同的设置下,我尝试通过使用以下代码更改retrieveOffices()
方法从应用程序内部创建数据:
private List<office_location_data> retrievePeople() {
List<office_location_data> list = new ArrayList<office_location_data>();
list.add(new office_location_data(1, "Bond"));
list.add(new office_location_data(2, "Cat"));
list.add(new office_location_data(3, "Dog"));
return list;
}
这将正常工作,并在输入第一个字母时显示选项。任何帮助表示赞赏。
以下是无效的代码。
我的活动是:
package tz.co.fsm.fas;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v7.app.AppCompatActivity;
import android.text.Editable;
import android.text.TextWatcher;
import android.widget.AutoCompleteTextView;
import android.widget.Button;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonArrayRequest;
import com.android.volley.toolbox.Volley;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
public class registerStep2 extends AppCompatActivity {
private String url;
SharedPreferences preferences;
SharedPreferences.Editor edit;
AutoCompleteTextView txtOfficeLocation, txtDepartment;
Button btnCompleteRegistration;
office_locations_adapter adapter;
List<office_location_data> listOffices;
List<office_location_data> list = new ArrayList<>();
// Import Class fas_functions
fas_functions Fas = new fas_functions(this);
private List<office_location_data> retrieveOffices() {
// Initiate Volley queue
RequestQueue queue = Volley.newRequestQueue(getApplicationContext());
// Add the api location (For JSON Requests we have to use GET and out the parameters in the url string (From Volley)
url = preferences.getString("server", "") + "/api/getofficelocations.php";
// Do the request and load the data into the array list to be used on autocomplete
JsonArrayRequest req = new JsonArrayRequest(Request.Method.GET, url ,null, new Response.Listener<JSONArray>() {
@Override
public void onResponse(JSONArray response) {
try {
for (int i = 0; i < response.length(); i++) {
JSONObject obj = response.getJSONObject(i);
list.add(new office_location_data(obj.getInt("office_id"), obj.getString("office_location")));
//list.add(new office_location_data(obj.getInt("office_id"), obj.getString("office_location")));
}
} catch (JSONException e) {
System.out.println(e.toString());
}
// Tell the adapter we have retrieved data and display
adapter.notifyDataSetChanged();
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
System.out.println(error.toString());
}
});
queue.add(req);
return list;
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_register_step2);
// Get elements
txtOfficeLocation = findViewById(R.id.txtOfficeLocation);
txtDepartment = findViewById(R.id.txtDeparment);
btnCompleteRegistration = findViewById(R.id.btnCompleteRegistration);
// Application preferences to check if we have already registered
preferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
// Immediately request for location permission
Fas.checkLocationPermission(this);
Fas.checkGPSandMobile(this);
listOffices = retrieveOffices();
adapter = new office_locations_adapter(getApplicationContext(), R.layout.office_locations_adapter_row,R.id.rowtxtOfficeLocation, listOffices);
txtOfficeLocation.setAdapter(adapter);
// Application preferences to check if we have already registered
preferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
TextWatcher textWatcher = new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
// Check if all fields are full so we can proceed
if (!txtOfficeLocation.getText().toString().isEmpty() && !txtDepartment.getText().toString().isEmpty()) {
btnCompleteRegistration.setEnabled(true);
} else {
btnCompleteRegistration.setEnabled(false);
}
}
};
txtOfficeLocation.addTextChangedListener(textWatcher);
txtDepartment.addTextChangedListener(textWatcher);
}
private void completeRegistration() {
// Edit the preferences
edit = preferences.edit();
// We have completed step 2 so add to preferences
edit.putBoolean("registrationstep2done", true);
}
} /* End of class */
自定义适配器如下:
package tz.co.fsm.fas;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Filter;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
public class office_locations_adapter extends ArrayAdapter<office_location_data> {
private Context context;
int resource, textViewResourceId;
private List<office_location_data> items, tempItems, suggestions;
public office_locations_adapter(Context context, int resource, int textViewResourceId, List<office_location_data> items) {
super(context, resource, textViewResourceId, items);
this.context = context;
this.resource = resource;
this.textViewResourceId = textViewResourceId;
this.items = items;
tempItems = new ArrayList<>(items); // this makes the difference.
suggestions = new ArrayList<>();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.office_locations_adapter_row, parent, false);
}
office_location_data office = items.get(position);
if (office != null) {
TextView lbloffice = view.findViewById(R.id.rowtxtOfficeLocation);
if (lbloffice != null) {
lbloffice.setText(office.getOffice_location());
}
}
return view;
}
// Method to return the filter
@Override
public Filter getFilter() {
return performFiletring;
}
// Create a new filter. Here we perform the filtering results and use this in the getFilter() method
Filter performFiletring = new Filter() {
@Override
public CharSequence convertResultToString(Object resultValue) {
String str = ((office_location_data) resultValue).getOffice_location();
return str;
}
@Override
protected FilterResults performFiltering(CharSequence constraint) {
if (constraint != null) {
suggestions.clear();
for (office_location_data offices : tempItems) {
if (offices.getOffice_location().toLowerCase().contains(constraint.toString().toLowerCase())) {
suggestions.add(offices);
}
}
FilterResults filterResults = new FilterResults();
filterResults.values = suggestions;
filterResults.count = suggestions.size();
return filterResults;
} else {
return new FilterResults();
}
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
List<office_location_data> filteredOffices = (ArrayList<office_location_data>) results.values;
if (results != null && results.count > 0) {
filteredOffices.clear();
for (office_location_data offices : filteredOffices) {
add(offices);
notifyDataSetChanged();
}
}
}
};
}
包含数据的类:
package tz.co.fsm.fas;
// Class to hold data for the autocomplete on the registration activity
public class office_location_data {
int office_id;
String office_location;
public void setOffice_id(int office_id) {
this.office_id = office_id;
}
public void setOffice_location(String office_location) {
this.office_location = office_location;
}
public int getOffice_id() {
return office_id;
}
public String getOffice_location() {
return office_location;
}
public office_location_data(int office_id, String office_location) {
this.office_id = office_id;
this.office_location = office_location;
}
}
自动完成行的布局为:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:layout_marginBottom="8dp"
android:orientation="horizontal"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/rowtxtOfficeLocation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1" />
</LinearLayout>
</android.support.constraint.ConstraintLayout>