- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有 3 个类(class),我希望使用自动完成文本框向用户显示来自 Web 服务(rest api)的某些数据(又名城市)。我已经在我自己的应用程序的各种功能上使用了这个实现,但是由于某种原因,textchangedlistener 中存在同步问题...
CitiesArrayAdapter.java(显示不同的 View ,在我的例子中是“城市,州”):
package com.android.lzgo.adapters;
import java.util.ArrayList;
import java.util.List;
import com.android.lzgo.activities.LiftSearchActivity;
import com.android.lzgo.activities.R;
import com.android.lzgo.models.City;
import com.android.lzgo.models.Lift;
import android.app.Activity;
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
public class CitiesArrayAdapter extends ArrayAdapter<City> {
private static final String TAG = CitiesArrayAdapter.class.getName();
private final ArrayList<City> cities;
private int viewResourceId;
public CitiesArrayAdapter(Context context, int textViewResourceId, ArrayList<City> results) {
super(context, textViewResourceId, results);
this.cities = results;
this.viewResourceId = textViewResourceId;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// assign the view we are converting to a local variable
View v = convertView;
if (v == null) {
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(viewResourceId, null);
}
City i = cities.get(position);
Log.d(TAG, "Here is my value: " + i);
if (i != null) {
TextView tt = (TextView) v.findViewById(android.R.id.text1);
Log.d(TAG, "Name: " + i.getName() + ", " + i.getProvince_name());
if (tt != null){
tt.setText("Name: " + i.getName() + ", " + i.getProvince_name());
}
}
// the view must be returned to our activity
return v;
}
CitiesResponderFragment.java(这是我从其余 api 获取值的方式):
package com.android.lzgo.fragment;
import java.util.ArrayList;
import java.util.List;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;
import com.android.lzgo.activities.LiftSearchActivity;
import com.android.lzgo.definitions.Constants;
import com.android.lzgo.models.City;
import com.android.lzgo.service.LzgoService;
import com.google.gson.Gson;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.widget.ArrayAdapter;
import android.widget.Toast;
public class CitiesResponderFragment extends LzgoResponderFragment {
private static String TAG = CitiesResponderFragment.class.getName();
private List<City> mCities;
ArrayAdapter<City> adapter;
private String enteredCharacters;
LiftSearchActivity activity;
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
activity = (LiftSearchActivity) getActivity();
// This gets called each time our Activity has finished creating itself.
getCities();
}
private void getCities() {
if (mCities == null && activity != null) {
Intent intent = new Intent(activity, LzgoService.class);
intent.setData(Uri.parse(Constants.REST_CITIES_AUTOCOMPLETE));
Bundle params = new Bundle();
params.putString("search", getenteredCharacters());
intent.putExtra(LzgoService.EXTRA_HTTP_VERB, LzgoService.GET);
intent.putExtra(LzgoService.EXTRA_PARAMS, params);
intent.putExtra(LzgoService.EXTRA_RESULT_RECEIVER, getResultReceiver());
// Here we send our Intent to our RESTService.
activity.startService(intent);
}
}
@Override
public void onRESTResult(int code, String result) {
Log.e(TAG, Integer.toString(code));
Log.e(TAG, result);
// Check to see if we got an HTTP 200 code and have some data.
if (code == 200 && result != null) {
mCities = getCitiessFromJson(result);
adapter = activity.getArrayAdapter();
adapter.clear();
for( City city : mCities){
//debugging
Log.d(TAG, "City : " + city.getName());
adapter.add(city);
adapter.notifyDataSetChanged();
}
getCities();
}
else {
Activity activity = getActivity();
if (activity != null && code == 400) {
Toast.makeText(activity, result, Toast.LENGTH_SHORT).show();
}
else
Toast.makeText(activity, "Failed to load lzgo data. Check your internet settings.", Toast.LENGTH_SHORT).show();
}
}
private List<City> getCitiessFromJson(String json) {
ArrayList<City> cityList = new ArrayList<City>();
Gson gson = new Gson();
try {
JSONObject citiesWrapper = (JSONObject) new JSONTokener(json).nextValue();
JSONArray cities = citiesWrapper.getJSONArray("cities");
for (int i = 0; i < cities.length(); i++) {
//JSONObject city = cities.getJSONObject(i);
String jsonCity = cities.getString(i);
City city = gson.fromJson( jsonCity, City.class );
//Log.e(TAG, "Hurray! Parsed json:" + city.getString("name"));
//cityList.add(city.getString("name"));
cityList.add(city);
}
}
catch (JSONException e) {
Log.e(TAG, "Failed to parse JSON.", e);
}
return cityList;
}
public String getenteredCharacters() {
return enteredCharacters;
}
public void setenteredCharacters(String characters) {
this.enteredCharacters = characters;
}
}
LiftSearchActivity.java(我的 FragmentActivity):
package com.android.lzgo.activities;
import java.util.ArrayList;
import com.android.lzgo.adapters.CitiesArrayAdapter;
import com.android.lzgo.fragment.CitiesResponderFragment;
import com.android.lzgo.models.City;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.View;
import android.widget.AutoCompleteTextView;
import android.widget.DatePicker;
public class LiftSearchActivity extends FragmentActivity{
private static final String TAG = LiftSearchActivity.class.getName();
// User lift input
private AutoCompleteTextView autoCityFrom;
private AutoCompleteTextView autoCityTo;
private DatePicker date;
private CitiesArrayAdapter adapter;
private ArrayList<City> mCities ;
int year , month , day;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.lift_search);
mCities = new ArrayList<City>();
adapter = new CitiesArrayAdapter(this,
android.R.layout.simple_dropdown_item_1line, mCities);
autoCityFrom = (AutoCompleteTextView) findViewById(R.id.cityFrom);
autoCityTo = (AutoCompleteTextView) findViewById(R.id.cityTo);
adapter.setNotifyOnChange(true);
autoCityFrom.setAdapter(adapter);
autoCityTo.setAdapter(adapter);
autoCityFrom.addTextChangedListener(new TextWatcher() {
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
// no need to do anything
}
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
if (((AutoCompleteTextView) autoCityFrom).isPerformingCompletion()) {
return;
}
if (charSequence.length() < 2) {
return;
}
String query = charSequence.toString();
getCities(query);
}
public void afterTextChanged(Editable editable) {
}
});
autoCityTo.addTextChangedListener(new TextWatcher() {
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
// no need to do anything
}
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
if (((AutoCompleteTextView) autoCityTo).isPerformingCompletion()) {
return;
}
if (charSequence.length() < 2) {
return;
}
String query = charSequence.toString();
getCities(query);
}
public void afterTextChanged(Editable editable) {
}
});
date = (DatePicker) findViewById(R.id.dpResult);
}
public void searchLifts(View view) {
Intent intent = new Intent(this, LiftsResultActivity.class);
//While autocomplete doesn't work hardcore value...
intent.putExtra("from", Integer.toString(9357)); // Sherbrooke
intent.putExtra("to", Integer.toString(6193)); // Montreal
intent.putExtra("date", Integer.toString(date.getMonth()+1) + "-" + Integer.toString(date.getDayOfMonth()) + "-" + Integer.toString(date.getYear()));
startActivity(intent);
}
public void getCities(String query) {
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
CitiesResponderFragment responder = (CitiesResponderFragment) fm.findFragmentByTag("RESTResponder");
responder = new CitiesResponderFragment();
responder.setenteredCharacters(query);
ft.add(responder, "RESTResponder");
ft.commit();
}
public CitiesArrayAdapter getArrayAdapter() {
// TODO Auto-generated method stub
return adapter;
}
}
我得到了正确的结果。但是我的服务似乎没有在我的 Activity 中填充我的数组适配器,当我尝试显示我的第一个“城市”时,我的适配器什么都不包含。我想知道我是否必须更改 notifydatasetchanged(我试过了,但没有用)。我有点困惑...有任何指示吗?
在调试应用程序时,我注意到 mObjects 的属性即使关联的 ArrayList 已清除 ArrayAdapter元素,然后属性 mOriginalValues 被填充第一次加载字符串。
最佳答案
在没有看到完整的代码库(+ 数据)的情况下,我不知道是否有人可以指出您的代码失败的原因。但我认为问题更多来自于你设置整个自动完成相关代码的方式,而不是一些明显的行错误。下面我将尝试解决其中的一些问题(从我的角度来看):
首先,在TextWatcher
来自 LiftSearchActivity
你调用getCities()
添加的方法,每次用户修改自动完成文本时,一个 Fragment
到 Activity
.我真的怀疑你想要这个,你应该看看只有一个 Fragment
在Activity
在其上调用刷新(或更新)方法,将新的过滤器文本传递给它。如果用户旋转手机,这些 fragment 也会因为配置更改而重新创建。
其次,在CitiesResponderFragment
你称之为 fragment 的类 getCities()
onActivityCreated
中的方法(如果您没有任何数据)启动更新服务(?!)。现在与第一点相关,您最终可能会做很多不必要的查询,例如,如果用户输入 4 个字符,然后决定删除其中一个字符,因为它不正确,您最终会添加 5 个 fragment ,来自哪 3 个将使服务启动/查询数据。
最后,我不确定你是否理解 AutoCompleteTextView
在引擎盖下工作。为了向下拉菜单提供建议 AutoCompleteTextView
小部件将过滤其适配器(adapter.getFilter()
)并将与过滤器匹配的项目显示为建议。我不知道你是否在 AutoCompleteTextView
上设置了一些阈值但最初,当您第一次设置 Activity
时,输入的前 3 个字符的自动完成将是空的,因为您从一个空的项目列表开始。 .前两个字符不会显示任何内容,因为您从一个空列表开始并且没有添加任何新 fragment (charSequence.length() < 2
)。第三个字符很可能也不会显示任何内容,因为创建 fragment 、启动服务和获取数据的开销几乎肯定会大于适配器过滤的工作(它仍然会看到最初的空列表) .我不知道你是否测试过,但是从第四个字符开始,适配器中应该有一些元素,并且过滤应该显示一些东西。清除适配器并在其中添加新数据只会使该数据可用于 AutoCompleteTextView
中输入的下一个字符。 .
进行过滤的正确方法是进一步扩展您的适配器并实现 getFilter()
返回您自己的方法 Filter
将在数据存储中查询新过滤项目的实现。过滤方法在后台线程上运行,只需做一些工作我认为您可以使用 Service
实现您当前的逻辑。和 REST 回调。
关于android - 具有自动完成功能的不同步 ArrayAdapter,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13547475/
我正在实现 IMAP 客户端,但 IMAP 邮箱同步出现问题。 首先,可以从 IMAP 服务器获取新邮件,但我不知道如何从邮箱中查找已删除的邮件。 我是否应该从服务器获取所有消息并将其与本地数据进行比
我研究线程同步。当我有这个例子时: class A { public synchronized void methodA(){ } public synchronized void met
嗨,我做了一个扩展线程的东西,它添加了一个包含 IP 的对象。然后我创建了该线程的两个实例并启动它们。他们使用相同的列表。 我现在想使用 Synchronized 来阻止并发更新问题。但它不起作用,我
我正在尝试使用 FTP 定期将小数据文件从程序上传到服务器。用户从使用 javascript XMLHttpRequest 函数读取数据的网页访问数据。这一切似乎都有效,但我正在努力解决由 FTP 和
我不知道如何同步下一个代码: javascript: (function() { var s2 = document.createElement('script'); s2.src =
关闭。这个问题需要更多focused .它目前不接受答案。 想改进这个问题吗? 更新问题,使其只关注一个问题 editing this post . 关闭 7 年前。 Improve this qu
一 点睛 1 Message 在基于 Message 的系统中,每一个 Event 也可以被称为 Message,Message 是对 Event 更高一个层级的抽象,每一个 Message 都有一个
一 点睛 1 Message 在基于 Message 的系统中,每一个 Event 也可以被称为 Message,Message 是对 Event 更高一个层级的抽象,每一个 Message 都有一个
目标:我所追求的是每次在数据库中添加某些内容时(在 $.ajax 到 Submit_to_db.php 之后),从数据库获取数据并刷新 main.php(通过 draw_polygon 更明显)。 所
我有一个重复动画,需要与其他一些 transient 动画同步。重复动画是一条在屏幕上移动 4 秒的扫描线。当它经过下面的图像时,这些图像需要“闪烁”。 闪烁的图像可以根据用户的意愿来来去去和移动。它
我有 b 个块,每个块有 t 个线程。 我可以用 __syncthreads() 同步特定块中的线程。例如 __global__ void aFunction() { for(i=0;i #
我正在使用azure表查询来检索分配给用户的所有错误实体。 此外,我更改了实体的属性以声明该实体处于处理模式。 处理完实体后,我将从表中删除该实体。 当我进行并行测试时,可能会发生查询期间,一个实体已
我想知道 SQLite 是如何实现它的。它基于文件锁定吗?当然,并不是每个访问它的用户都锁定了整个数据库;那效率极低。它是基于多个文件还是仅基于一个大文件? 如果有人能够简要概述一下 sqlite 中
我想post到php,当id EmpAgree1时,然后它的post变量EmpAgree=1;当id为EmpAgree2时,则后置变量EmpAgree=2等。但只是读取i的最后一个值,为什么?以及如何
CUBLAS 文档提到我们在读取标量结果之前需要同步: “此外,少数返回标量结果的函数,例如 amax()、amin、asum()、rotg()、rotmg()、dot() 和 nrm2(),通过引用
我知道下面的代码中缺少一些内容,我的问题是关于 RemoteImplementation 中的同步机制。我还了解到该网站和其他网站上有几个关于 RMI 和同步的问题;我在这里寻找明确的确认/矛盾。 我
我不太确定如何解决这个问题......所以我可能需要几次尝试才能正确回答这个问题。我有一个用于缓存方法结果的注释。我的代码目前是一个私有(private)分支,但我正在处理的部分从这里开始: http
我对 Java 非常失望,因为它不允许以下代码尽可能地并发移动。当没有同步时,两个线程会更频繁地切换,但是当尝试访问同步方法时,在第二个线程获得锁之前以及在第一个线程获得锁之前再次花费太长时间(比如
过去几周我一直在研究java多线程。我了解了synchronized,并理解synchronized避免了多个线程同时访问相同的属性。我编写此代码是为了在同一线程中运行两个线程。 val gate =
我有一个关于 Java 同步的简单问题。 请假设以下代码: public class Test { private String address; private int age;
我是一名优秀的程序员,十分优秀!