Android EditText setText方法踩坑实录

作者: 野岗狼沟兜 | 来源:发表于2018-07-04 00:40 被阅读54次

1、平平常常中就这样开始

  • 某一天,我准备做一个搜索功能,这个搜索功能呢大概是在主活动A中,用EditText接收输入,当EditText监听到输入框中内容有变化,跳转到活动B中,活动B中准备有搜索历史记录等等,等在活动B中确定好搜索关键词后,跳回到活动A中,执行搜索,并显示搜索结果……一切顺顺利利,然后呢,懵逼了,我回不了活动A了。
    当时的情况大致是这样的,
    布局文件: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="输入点啥呗"
        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,添加文本监听
        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="我就是那个准备搜索关键词,历史记录等等等等的活动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) {
                        //将取得关键字传递到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,至此大功告成,我成功复原了当时我大致做法,也还原了当时的Bug:在A中有输入时,跳到B,在B中确定好关键词后,点击搜索(你的搜索在哪里,让你们看下图吧)


    1.png
  • 看到右下角我圈起来的那个搜索按钮了吗,布局文件照着我那个写,监听就是editTextKeyWords.setOnEditorActionListener(……),布局中重要的是
     android:inputType="text"
        android:singleLine="true"
        android:imeOptions="actionSearch"

这个主要是参看这位大大的,当然了,在此这不算重点,重点是我又成功写了个Bug。当时项目挺急的,我弄了半天没弄明白,(我一直以为是A活动因为setText而崩溃了,然而没有log……当然,最终证明似乎不是这样子。),无奈之下,福灵心至,想到:

2、用了setHint()解决了当务之急

  • 无奈之下选择了该方法,问题成功解决,也没什么明显瑕疵,就是心理一直惦记着,这他丫的问题出在什么地方呢,定位当然是定位到了A活动中的searchEditText.setText(keyword)这一句。
    后来加了几天班,等稍微有空了,我再回头瞧瞧,莫非,谷歌给我们写了个小bug,结果嘛:事实证明,好像这东西是自己的锅。

3、发现敌踪迹

  • 当时我实在onResume()调用searchEditText.setText(keyword)这几句的,所以问题显得比我上面写的要隐蔽些。当然,有空了之后,我进入setText方法,一步步执行,当然了,没发现明显问题。只是我偶尔会发现它会不经意间往beforeTextChanged等这一两个方法中眺一下,那么想一想我在里面又做了什么……,似乎我发现问题所在了。那么有了猜测,对该方法添加log,我们队log做下修改,使其能明确地显示程序执行顺序,修改代码如下:
    ActivityA.java
public class ActivityA extends AppCompatActivity {
    private EditText searchEditText;
    public static int executeOrder=0;//表示log执行顺序,进而推测代码执行顺序
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.d("editTextSetText","after setContentView "+executeOrder++);
        //找到EditText,添加文本监听
        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) {
                        //将取得关键字传递到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;
            }
        });
    }
}
  • 执行一遍,log如下:


    2.png
  • 上述log显示,做如下解读:
    1、 启动应用,执行初始化,打印 0
    2、输入内容,执行1,2,3,到启动活动B
    3、活动B初始化执行 4
    5、 活动B中点击搜索 5,并启动活动A
    6、A再一次初始化 执行6
    7、问题出来了,为什么会执行7、8、9,此时我们并没有EditText输入内容,但是监听触发了。
    8、 执行9之后,启动活动B,执行11没问题,但是10的顺序按理说应该在6之后、紧接着6.
  • 尽管未能完全解读这个执行顺序,但是,写的程序陷入了一个类似死循环的bug是没有问题的,这也就解开了为什么返回不了A活动的问题,并不是不能返回A,而是返回A之后又跳转到B了

进一步调试,在关键节点增加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信息:


    3.png
  • 关键点我已经标出来了,在7和11间,有了监听方法的执行,说明:EditText的setText方法会触发 文本变化的监听,这就是此次踩坑的根源。

4、 捕获凶手:setText()方法会触发EditText文本变化的监听

5、解决方案:将setText设置在设置监听之前,或者用setHint也可以。

  • 如上,找出问题症结之后,解决办法就很简单了,我们将setText写在设置监听之前就可以避免该坑,或者干脆用setHint方法。
  • over.

相关文章

  • Android EditText setText方法踩坑实录

    1、平平常常中就这样开始 某一天,我准备做一个搜索功能,这个搜索功能呢大概是在主活动A中,用EditText接收输...

  • Android 日常踩坑

    1、Android NDK开发踩坑 踩坑环境 Android Studio 3.4.1,JDK 1.8 1、为什么...

  • EditText和TextView可以横向滑动

    1、EditText横向滑动方法 android:maxLines="1" android:singleLine=...

  • ExditText动态设置文字值

    直接设置text无效,需要添加如下参数即可editText.setText("string", TextView....

  • 给TextField 赋值

    在Android开发中 EditTextView 复制直接调用setText()方法即可,那么在flutter中我...

  • Android共享元素

    在这里记录一下android共享元素的方法,踩了满多坑的,其实蛮简单的,Android共享是从Android5.0...

  • setText坑

    mView.setText(data.name + " - " + data.age);当name,age为nul...

  • Vue踩坑实录(二)

    在上一篇中说了一下踩过的前三个坑,剩下的坑就在这篇中全部搞定吧。Vue踩坑实录(一) Vue-cli .js?.V...

  • EditText获取多个按钮中的文字内容

    EditText获取字符串可以通过setText()方法来设置,但是通常下一个内容都会覆盖前一个内容,这样有时就不...

  • fastlane 踩坑实录

    这个世界是懒人创造的。 人懒了就会发明各种各样的工具,或者寻找各种各样能够给自己偷懒机会的工具,当然我还停留在使用...

网友评论

    本文标题:Android EditText setText方法踩坑实录

    本文链接:https://www.haomeiwen.com/subject/pgqkuftx.html