Search code examples
androidkotlinautocompletetextview

AutoCompleteTextView(AppCompat) issue while no character (Kotlin)


I am using AutoCompleteTextView(AppCompat) by ArrayAdapter. I am getting result successfully when I type some character. But when I remove first character of this component, it consider null object in filter and giving me null pointer exception.

What I tried so far

  1. From few old post I found that setThreshold can be solution, but its not working.
  2. I customized AppCompat's AutoCompleteTextView class and try to handle replaceText and performFiltering but its not working.
  3. I try to restrict backspace on 1st character by adding setOnKeyListener, but its not getting called because its totally controlled by Filter class after having some result in cache.
  4. Customize android.widget.filter class, but its not allowed by OS, as its restricted by Android OS to use out of Package.

Code :

class MyAutoCompleteTextView(context: Context?, attrs: AttributeSet?) : AppCompatAutoCompleteTextView(context, attrs) {

    override fun replaceText(text: CharSequence?) {
        super.replaceText("")
    }

    override fun performFiltering(text: CharSequence?, keyCode: Int) {
        super.performFiltering("", keyCode)
    }
}

XML :

<com.spec.trailapp.utils.taglibs.MyAutoCompleteTextView
    android:id="@+id/autocomplTagged"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentTop="true"
    android:layout_margin="10dp"
    android:inputType="text"
    android:textCursorDrawable="@drawable/color_cursor"
    android:background="@null"
    android:completionThreshold="1"

    android:fontFamily="@font/brandotextlight"
    android:hint="@string/txt_who_did_you_go_with"
    android:textColorHint="@color/itinerary_title_txt_color"
    android:textColor="@color/colorBlack"
    android:maxLines="1"/>

Adapter

class AutoSuggestAdapter(@NonNull context: Context, resource: Int) : ArrayAdapter<String>(context, resource),
    Filterable {
        private val mlistData: MutableList<String>
        var alLocalresult: ArrayList<ResultItem?> = ArrayList<ResultItem?>()

        init {
            mlistData = ArrayList()
        }

        fun setData(result: ArrayList<ResultItem>) {
            /*mlistData.clear()
            mlistData.addAll(list)*/

            if (result != null) {
                this.alLocalresult.addAll(result)
            }
        }

        override fun getCount(): Int {
            if(alLocalresult==null)
            {
                return 0
            } else
                return alLocalresult.size
        }

        override fun getItem(position: Int): String {
            return alLocalresult.get(position)?.firstName + " " + alLocalresult.get(position)?.lastName
            // return result
        }

        /**
         * Used to Return the full object directly from adapter.
         *
         * @param position
         * @return
         */
        /*fun getObject(position: Int): String {
            return mlistData[position]
        }*/

        @NonNull
        override fun getFilter(): Filter {
            return object : Filter() {
                protected override fun performFiltering(constraint: CharSequence?): FilterResults {
                    val filterResults = FilterResults()
                    if (constraint != null) {
                        filterResults.values = alLocalresult
                        filterResults.count = alLocalresult.size

                    }
                    return filterResults
                }

                protected override fun publishResults(constraint: CharSequence, results: FilterResults?) {
                    if (results != null && results!!.count > 0) {
                        notifyDataSetChanged()
                    } else
                    {
                    }
                }
            }
        }
    }

MainAvtivity :

var autoSuggestAdapter = AutoSuggestAdapter(
    this,
    android.R.layout.simple_dropdown_item_1line
)
autocomplTagged.setThreshold(1)
autocomplTagged.setAdapter(autoSuggestAdapter)
autoSuggestAdapter.setData(frindslist.data!!.result!!)

Crash Log

java.lang.IllegalArgumentException: Parameter specified as non-null is null: method kotlin.jvm.internal.Intrinsics.checkParameterIsNotNull, parameter constraint
        at com.spec.trailapp.utils.taglibs.AutoSuggestAdapter$getFilter$1.publishResults(AutoSuggestAdapter.kt)
        at android.widget.Filter$ResultsHandler.handleMessage(Filter.java:282)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:154)
        at android.app.ActivityThread.main(ActivityThread.java:6123)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:757)

Please help on this. Even some clue will be niice for me.


Solution

  • protected override fun publishResults(constraint: CharSequence, results: FilterResults?) {
                        if (results != null && results!!.count > 0) {
                            notifyDataSetChanged()
                        } else
                        {
                        }
                    }
    

    constraint: CharSequence . <-- in this method is defined as nonNullable CharSequence. But your providing a null as CharSequence.

    What will probably fix your issue is

    protected override fun publishResults(constraint: CharSequence?, results: FilterResults?) {
                        if (results != null && results!!.count > 0) {
                            notifyDataSetChanged()
                        } else
                        {
                        }
        }
    

    Just add a ? behind CharSequence. Now you defined that it's possible for constraint to be null