Android中EditText setText方法的踩坑實(shí)戰(zhàn)
1、平平常常中就這樣開始
某一天,我準(zhǔn)備做一個搜索功能,這個搜索功能呢大概是在主活動A中,用EditText接收輸入,當(dāng)EditText監(jiān)聽到輸入框中內(nèi)容有變化,跳轉(zhuǎn)到活動B中,活動B中準(zhǔn)備有搜索歷史記錄等等,等在活動B中確定好搜索關(guān)鍵詞后,跳回到活動A中,執(zhí)行搜索,并顯示搜索結(jié)果……一切順順利利,然后呢,懵逼了,我回不了活動A了。
當(dāng)時的情況大致是這樣的,
布局文件:activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout 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" android:orientation="vertical" tools:context=".ActivityA"> <EditText android:inputType="text" android:singleLine="true" android:imeOptions="actionSearch" android:id="@+id/et_search" android:textSize="24sp" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="輸入點(diǎn)啥唄" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" /> <TextView android:textSize="24sp" android:gravity="center" android:layout_weight="1" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="我是主活動啦"/> </LinearLayout>
活動A:AcitivityA.java
public class ActivityA extends AppCompatActivity {
private EditText searchEditText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//找到EditText,添加文本監(jiān)聽
searchEditText=findViewById(R.id.et_search);
searchEditText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
Log.d("editTextSetText","beforeTextChanged");
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
Log.d("editTextSetText","onTextChanged");
}
@Override
public void afterTextChanged(Editable s) {
Log.d("editTextSetText","afterTextChanged");
startActivity(new Intent(ActivityA.this,ActivityB.class));
}
});
//接收B活動傳遞過來的keywords,并顯示在輸入框中
String keyword=getIntent().getStringExtra("keywords");
if(keyword!=null)
searchEditText.setText(keyword);
}
活動B布局文件:activity_search.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <EditText android:id="@+id/et_search_keywords" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="輸入你想要找的東西" android:textSize="24sp" android:inputType="text" android:singleLine="true" android:imeOptions="actionSearch"/> <TextView android:textSize="24sp" android:gravity="center" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:text="我就是那個準(zhǔn)備搜索關(guān)鍵詞,歷史記錄等等等等的活動B啦" /> </LinearLayout>
活動B:ActivityB.java
public class ActivityB extends AppCompatActivity {
private EditText editTextKeyWords;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_search);
editTextKeyWords = findViewById(R.id.et_search_keywords);
editTextKeyWords.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
//將取得關(guān)鍵字傳遞到A中
String keywords = v.getText().toString().trim();
Intent intent = new Intent(ActivityB.this, ActivityA.class);
intent.putExtra("keywords", keywords);
Log.d("editTextSetText", "B keywords:" + keywords);
startActivity(intent);
ActivityB.this.finish();
}
return false;
}
});
}
}
OK,至此大功告成,我成功復(fù)原了當(dāng)時我大致做法,也還原了當(dāng)時的Bug:在A中有輸入時,跳到B,在B中確定好關(guān)鍵詞后,點(diǎn)擊搜索(你的搜索在哪里,讓你們看下圖吧)

看到右下角我圈起來的那個搜索按鈕了嗎,布局文件照著我那個寫,監(jiān)聽就是editTextKeyWords.setOnEditorActionListener(……),布局中重要的是
android:inputType="text" android:singleLine="true" android:imeOptions="actionSearch"
這個主要是參看這位大大的,當(dāng)然了,在此這不算重點(diǎn),重點(diǎn)是我又成功寫了個Bug。當(dāng)時項(xiàng)目挺急的,我弄了半天沒弄明白,(我一直以為是A活動因?yàn)閟etText而崩潰了,然而沒有l(wèi)og……當(dāng)然,最終證明似乎不是這樣子。),無奈之下,福靈心至,想到:
2、用了setHint()解決了當(dāng)務(wù)之急
無奈之下選擇了該方法,問題成功解決,也沒什么明顯瑕疵,就是心理一直惦記著,這他丫的問題出在什么地方呢,定位當(dāng)然是定位到了A活動中的searchEditText.setText(keyword)這一句。
后來加了幾天班,等稍微有空了,我再回頭瞧瞧,莫非,谷歌給我們寫了個小bug,結(jié)果嘛:事實(shí)證明,好像這東西是自己的鍋。
3、發(fā)現(xiàn)敵蹤跡
當(dāng)時我實(shí)在onResume()調(diào)用searchEditText.setText(keyword)這幾句的,所以問題顯得比我上面寫的要隱蔽些。當(dāng)然,有空了之后,我進(jìn)入setText方法,一步步執(zhí)行,當(dāng)然了,沒發(fā)現(xiàn)明顯問題。只是我偶爾會發(fā)現(xiàn)它會不經(jīng)意間往beforeTextChanged等這一兩個方法中眺一下,那么想一想我在里面又做了什么……,似乎我發(fā)現(xiàn)問題所在了。那么有了猜測,對該方法添加log,我們隊(duì)log做下修改,使其能明確地顯示程序執(zhí)行順序,修改代碼如下:
ActivityA.java
public class ActivityA extends AppCompatActivity {
private EditText searchEditText;
public static int executeOrder=0;//表示log執(zhí)行順序,進(jìn)而推測代碼執(zhí)行順序
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d("editTextSetText","after setContentView "+executeOrder++);
//找到EditText,添加文本監(jiān)聽
searchEditText=findViewById(R.id.et_search);
searchEditText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
Log.d("editTextSetText","beforeTextChanged "+executeOrder++);
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
Log.d("editTextSetText","onTextChanged "+executeOrder++);
}
@Override
public void afterTextChanged(Editable s) {
Log.d("editTextSetText","afterTextChanged "+executeOrder++);
startActivity(new Intent(ActivityA.this,ActivityB.class));
}
});
//接收B活動傳遞過來的keywords,并顯示在輸入框中
String keyword=getIntent().getStringExtra("keywords");
if(keyword!=null) {
searchEditText.setText(keyword);
Log.d("editTextSetText","after set text "+executeOrder++);
/*searchEditText.setHint(keyword);*/
}
}
}
ActivityB.java
public class ActivityB extends AppCompatActivity {
private EditText editTextKeyWords;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_search);
Log.d("editTextSetText", "B after setContentView " +ActivityA.executeOrder++);
editTextKeyWords = findViewById(R.id.et_search_keywords);
editTextKeyWords.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
//將取得關(guān)鍵字傳遞到A中
String keywords = v.getText().toString().trim();
Intent intent = new Intent(ActivityB.this, ActivityA.class);
intent.putExtra("keywords", keywords);
Log.d("editTextSetText", "B keywords:" + keywords+" " +ActivityA.executeOrder++);
startActivity(intent);
ActivityB.this.finish();
}
return false;
}
});
}
}
執(zhí)行一遍,log如下:

上述log顯示,做如下解讀:
1、 啟動應(yīng)用,執(zhí)行初始化,打印 0
2、輸入內(nèi)容,執(zhí)行1,2,3,到啟動活動B
3、活動B初始化執(zhí)行 4
5、 活動B中點(diǎn)擊搜索 5,并啟動活動A
6、A再一次初始化 執(zhí)行6
7、問題出來了,為什么會執(zhí)行7、8、9,此時我們并沒有EditText輸入內(nèi)容,但是監(jiān)聽觸發(fā)了。
8、 執(zhí)行9之后,啟動活動B,執(zhí)行11沒問題,但是10的順序按理說應(yīng)該在6之后、緊接著6.
盡管未能完全解讀這個執(zhí)行順序,但是,寫的程序陷入了一個類似死循環(huán)的bug是沒有問題的,這也就解開了為什么返回不了A活動的問題,并不是不能返回A,而是返回A之后又跳轉(zhuǎn)到B了。
進(jìn)一步調(diào)試,在關(guān)鍵節(jié)點(diǎn)增加log,我們再setText前后增加log
if(keyword!=null) {
Log.d("editTextSetText","after set text "+executeOrder++);
searchEditText.setText(keyword);
Log.d("editTextSetText","after set text "+executeOrder++);
/*searchEditText.setHint(keyword);*/
}
log信息:

關(guān)鍵點(diǎn)我已經(jīng)標(biāo)出來了,在7和11間,有了監(jiān)聽方法的執(zhí)行,說明:EditText的setText方法會觸發(fā) 文本變化的監(jiān)聽,這就是此次踩坑的根源。
4、 捕獲兇手:setText()方法會觸發(fā)EditText文本變化的監(jiān)聽
5、解決方案:將setText設(shè)置在設(shè)置監(jiān)聽之前,或者用setHint也可以。
如上,找出問題癥結(jié)之后,解決辦法就很簡單了,我們將setText寫在設(shè)置監(jiān)聽之前就可以避免該坑,或者干脆用setHint方法。
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。
- Android中ViewPager組件的基本用法及實(shí)現(xiàn)圖片切換的示例
- android Gallery組件實(shí)現(xiàn)的iPhone圖片滑動效果實(shí)例
- Android組件Glide實(shí)現(xiàn)圖片平滑滾動效果
- Android自定義組件獲取本地圖片和相機(jī)拍照圖片
- Android可循環(huán)顯示圖像的Android Gallery組件用法實(shí)例
- Android高級組件Gallery畫廊視圖使用方法詳解
- Android高級組件ImageSwitcher圖像切換器使用方法詳解
- 淺析Android Studio 3.0 升級各種坑(推薦)
- Android WebView使用的技巧與一些坑
- Android開發(fā)之StackView用法和遇到的坑分析
相關(guān)文章
提升Android應(yīng)用視覺吸引效果的10個UI設(shè)計(jì)技巧
在Android應(yīng)用開發(fā)中,風(fēng)格和設(shè)計(jì)或許不是最關(guān)鍵的要素,但它們在決定Android應(yīng)用成功與否上確實(shí)扮演重要的角色,以下是10個Android應(yīng)用的UI設(shè)計(jì)技巧,還有個附加技巧,感興趣的朋友可以了解下哦2013-01-01
Android設(shè)置默認(rèn)鎖屏壁紙接口的方法
這篇文章主要介紹了Android默認(rèn)鎖屏壁紙接口的設(shè)置方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-01-01
Android判斷json格式將錯誤信息提交給服務(wù)器
今天小編就為大家分享一篇關(guān)于Android判斷json格式將錯誤信息提交給服務(wù)器,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2019-03-03
Android 8.0不能自動安裝APK問題的解決方法(完美適配)
這篇文章主要給大家介紹了關(guān)于Android 8.0不能自動安裝APK問題的解決方法(完美適配),這里的自動安裝是指下載完成后,自動彈出安裝界面,而不是靜默安裝APK,文中介紹的非常詳細(xì),需要的朋友可以參考下2018-07-07
Android開發(fā)準(zhǔn)確獲取手機(jī)IP地址的兩種方式
這篇文章主要介紹了Android開發(fā)準(zhǔn)確獲取手機(jī)IP地址的兩種方式,需要的朋友可以參考下2020-03-03
Android無需讀寫權(quán)限通過臨時授權(quán)讀寫用戶文件詳解
這篇文章主要為大家介紹了Android無需讀寫權(quán)限通過臨時授權(quán)讀寫用戶文件詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03

