【问题标题】:Autocomplete address on android using geocoder使用地理编码器在android上自动完成地址
【发布时间】:2012-05-15 01:48:37
【问题描述】:

为了使用地理编码器在 android 上自动完成一个简单的地址,我尝试了耐心并最终决定寻求帮助。

原代码参考:Geocoder autocomplete in android

所以在下面的代码中,正在发生的所有事情都是在用户在 autoCompleteTextView 中键入时尝试自动完成地址。我正在调用函数在 runOnUiThread 中执行实际工作,希望 UI 在用户输入时不会冻结。但是 UI 在阈值(3 个字符)之后冻结,并且可能的地址的下拉列表出现在它自己节奏,并非总是如此。

如果你们能告诉我哪里出错了....提前谢谢

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.location.Address;
import android.location.Geocoder;
import android.os.Bundle;
import android.os.Handler;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;

public class AlarmActivity extends Activity implements TextWatcher {
private static final int THRESHOLD = 3;
private String latitude, longitude;
private List<Address> autoCompleteSuggestionAddresses;
private ArrayAdapter<String> autoCompleteAdapter;



/** Called when the activity is first created. */
@Override
public void onCreate(Bundle icicle) {
    super.onCreate(icicle);
    setContentView(R.layout.hw);
    setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL);
    autoCompleteAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line, new ArrayList<String>());
    autoCompleteAdapter.setNotifyOnChange(false);
    AutoCompleteTextView locationinput = (AutoCompleteTextView) findViewById(R.id.locationInput);
    locationinput.addTextChangedListener(this);
    locationinput.setOnItemSelectedListener(this);
    locationinput.setThreshold(THRESHOLD);
    locationinput.setAdapter(autoCompleteAdapter);

}

@Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {

}

@Override
public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
final String value = arg0.toString();

if (!"".equals(value) && value.length() >= THRESHOLD) {

    Thread t = new Thread() {
        public void run() {
            try {

                runOnUiThread(new Runnable() {
                    public void run() {
                        notifyResult(value);
                    }
                });
            } catch (Exception e) {}
        }
    };
    t.start();


} else {
    autoCompleteAdapter.clear();
}
}

@Override
public void afterTextChanged(Editable arg0) {
}


private void notifyResult(String value) {
     try {
            autoCompleteSuggestionAddresses = new Geocoder(getBaseContext()).getFromLocationName(value, 10);

            //notifyResult(autoCompleteSuggestionAddresses);

            latitude = longitude = null;
            autoCompleteAdapter.clear();
            for (Address a : autoCompleteSuggestionAddresses) {
                Log.v("Nohsib", a.toString());
                String temp = ""+ a.getFeatureName()+" "+a.getCountryName()+" "+a.getPostalCode();  

                autoCompleteAdapter.add(temp);
            }
            autoCompleteAdapter.notifyDataSetChanged();



        } catch (IOException ex) {
          //  Log.e(GeoCoderAsyncTask.class.getName(), "Failed to get autocomplete suggestions", ex);
        }

}

}

【问题讨论】:

    标签: android android-layout android-intent android-widget


    【解决方案1】:

    我认为 UI 冻结的原因是因为即使您从单独的线程调用 notifyResult,它仍然在 UI 线程上运行。解决此问题的方法是改用AsyncTask

    类似:

    private class GetSuggestions extends AsyncTask<String, Void, Void> {
         protected Long doInBackground(String... search) {
             value = search[0];
             try {
            autoCompleteSuggestionAddresses = new Geocoder(getBaseContext()).getFromLocationName(value, 10);
    
            //notifyResult(autoCompleteSuggestionAddresses);
    
            latitude = longitude = null;
            autoCompleteAdapter.clear();
            for (Address a : autoCompleteSuggestionAddresses) {
                Log.v("Nohsib", a.toString());
                String temp = ""+ a.getFeatureName()+" "+a.getCountryName()+" "+a.getPostalCode();  
    
                autoCompleteAdapter.add(temp);
            }
    
        } catch (IOException ex) {
          //  Log.e(GeoCoderAsyncTask.class.getName(), "Failed to get autocomplete suggestions", ex);
        }
         }
    
         protected void onPostExecute(Long result) {
             autoCompleteAdapter.notifyDataSetChanged();
         }
     }
    

    然后就可以通过调用new GetSuggestions().execute(value)来启动任务了;

    【讨论】:

    • @Michaeldcooney:感谢您的回复。但是,我已经尝试过这种方法,并且它给出了编辑到您的解决方案中的异常。所以我尝试通过 runOnUiThread 调用 autoCompleteAdapter.notifyDataSetChanged() ,但这根​​本没有给出建议下拉列表。有什么建议吗?
    • 如果上面的异常不可见:原因:android.view.ViewRoot$CalledFromWrongThreadException:只有创建视图层次结构的原始线程才能触摸它的视图。
    • 如果您想知道,这是因为您在异步任务中修改适配器的数据而导致崩溃。您应该简单地将 autoCompleteSuggestionAddresses 作为返回值传递,然后在 onPostExecute 方法中评估并将它们添加到适配器。因此,不是返回 Long,而是返回类型类似于 List
    猜你喜欢
    • 1970-01-01
    • 2019-04-07
    • 2015-04-25
    • 2019-06-02
    • 2011-12-04
    • 2019-02-13
    • 1970-01-01
    • 2013-09-28
    • 2012-10-24
    相关资源
    最近更新 更多