Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
215 views
in Technique[技术] by (71.8m points)

android - “search?.actionView as SearchView” crashes moving to the Second Activity

I am building a simple app (in Kotlin), which has a simple button in MainActivity.kt, that when clicked opens a second activity. The second activity has an array (from strings.xml). When the selected list item the result should be passed to the first activity.

When I click on the button to go to the second activity it crashes (on “ val searchView : SearchView = search?.actionView as SearchView”) – although it is reporting errors in the log (which I don’t really understand).

I’m using the androidx.appcompat.widget.SearchView library which I had seen problems using the old library, so I don’t think it is that.

Any help really appreciated - thanks.

MainActivity.kt

class MainActivity : AppCompatActivity() {

private val SEARCH_ACTIVITY_REQUEST_CODE = 1

/* THE GUTS OF IT */
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    Searchbutton.setOnClickListener {
        Log.d("TAG", "MainActivity 1- JH")
        val intent = Intent(this, SearchActivity::class.java)
        Log.d("TAG", "MainActivity 2- JH")
        startActivityForResult(intent, SEARCH_ACTIVITY_REQUEST_CODE)
        Log.d("TAG", "MainActivity 3- JH")
    }
}

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    Log.d("TAG", "onActivityResult starting 100 - JH")
    super.onActivityResult(requestCode, resultCode, data)

    Log.d("TAG", "onActivityResult 101 - JH")
    if (requestCode == SEARCH_ACTIVITY_REQUEST_CODE) {
        val gotthisInt = data?.getStringExtra("result")

        Log.d("TAG", "What was received  JH = $gotthisInt")
        if (resultCode == RESULT_OK) {
            /* val gotthisInt = data?.getStringExtra("result") */
            val gotPosition = data?.getStringExtra("position")
            Log.d("TAG", "What was POSITION  JH = $gotPosition")
        }
    }
}

}

Activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
 <androidx.constraintlayout.widget.ConstraintLayout 
 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"
tools:context=".MainActivity">

<!-- Debug - to be deleted -->
<TextView
    android:id="@+id/textDebug"
    android:layout_width="69dp"
    android:layout_height="40dp"
    android:layout_marginBottom="104dp"
    android:text="DEBUG HETE"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent" />

<Button
    android:id="@+id/Searchbutton"
    android:layout_width="58dp"
    android:layout_height="50dp"
    android:layout_marginBottom="80dp"
    android:drawableLeft="@android:drawable/ic_menu_search"
    app:layout_constraintBottom_toTopOf="@+id/textDebug"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

SearchActivity.kt

class SearchActivity : AppCompatActivity() {
private lateinit var toolbar: Toolbar
lateinit var adapter: ArrayAdapter<*>
private lateinit var listView: ListView
private lateinit var emptyView: TextView

override fun onCreate(savedInstanceState: Bundle?) {
    Log.d("TAG", "SearchActivity OnCreate Starts JH")

    super.onCreate(savedInstanceState)

    setContentView(R.layout.search_main)

    title = "Search App"
    toolbar = findViewById(R.id.toolbar)
    listView = findViewById(R.id.listView)
    emptyView = findViewById(R.id.emptyView)

    adapter = ArrayAdapter<Any?>(this, android.R.layout.simple_list_item_1,
        resources.getStringArray(R.array.vegetables))
    listView.adapter = adapter

    listView.onItemClickListener = OnItemClickListener { adapterView, _, i, _ ->
        Toast.makeText(this@SearchActivity, adapterView.getItemAtPosition(i).toString(),
            Toast.LENGTH_SHORT).show()
    }
    listView.emptyView = emptyView
}

override fun onCreateOptionsMenu(menu: Menu): Boolean {
    Log.d("TAG", "onCreateOptionsMenu Starts JH")

    menuInflater.inflate(R.menu.menu, menu)
    Log.d("TAG", "onCreateOptionsMenu 901 JH")
    val search = menu.findItem(R.id.appSearchBar)
    Log.d("TAG", "onCreateOptionsMenu 902 JH")
    /*val searchView = search.actionView as SearchView CRASH */
    val searchView : SearchView = search?.actionView as SearchView  /* This crashes for my code, works here */

    Log.d("TAG", "onCreateOptionsMenu 903 JH")

    searchView.queryHint = "Search"
    Log.d("TAG", "onCreateOptionsMenu 904 JH")

    listView.setOnItemClickListener(OnItemClickListener { parent, view, position, id ->
        val intent = Intent()
        val theItemClicked = String()
        /* Log.d("TAG", "onCreateOptionsMenu - 209 - Gets here JH")
            theItemClicked = list[position].toString() */

        intent.putExtra("result", "this one")
        intent.putExtra("position", "hello")
        setResult(RESULT_OK, intent)
        finish()
    })

    searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
        override fun onQueryTextSubmit(query: String?): Boolean {
            return false
        }
        override fun onQueryTextChange(newText: String?): Boolean {
            adapter.filter.filter(newText)
            return true
        }
    })
    return super.onCreateOptionsMenu(menu)
}

}

Search_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
tools:context=".SearchActivity">
    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="?attr/colorBackgroundFloating"
        android:minHeight="?attr/actionBarSize" />
    <ListView
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    <TextView
        android:id="@+id/emptyView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="No Results"
        android:textSize="20sp"
        android:visibility="gone" />

nav_menu.xml

<?xml version="1.0" encoding="utf-8"?>
<item
    android:id="@+id/appSearchBar"
    android:icon="@drawable/ic_baseline_search_24"
    android:title="Search"
    app:actionViewClass="androidx.appcompat.widget.SearchView"
    app:showAsAction="always" />

logcat Errors These errors are shown when I click to move to the second activity:

2021-01-27 22:54:47.956 1429-1429/com.dbtest.VegJanv20211 E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.dbtest.VegJanv20211, PID: 1429
kotlin.TypeCastException: null cannot be cast to non-null type androidx.appcompat.widget.SearchView
    at com.dbtest.VegJanv20211.SearchActivity.onCreateOptionsMenu(SearchActivity.kt:55)
    at android.app.Activity.onCreatePanelMenu(Activity.java:4074)
    at androidx.fragment.app.FragmentActivity.onCreatePanelMenu(FragmentActivity.java:325)
    at androidx.appcompat.view.WindowCallbackWrapper.onCreatePanelMenu(WindowCallbackWrapper.java:94)
    at androidx.appcompat.app.AppCompatDelegateImpl$AppCompatWindowCallback.onCreatePanelMenu(AppCompatDelegateImpl.java:3070)
    at androidx.appcompat.app.AppCompatDelegateImpl.preparePanel(AppCompatDelegateImpl.java:1895)
    at androidx.appcompat.app.AppCompatDelegateImpl.doInvalidatePanelMenu(AppCompatDelegateImpl.java:2176)
    at androidx.appcompat.app.AppCompatDelegateImpl$2.run(AppCompatDelegateImpl.java:271)
    at android.os.Handler.handleCallback(Handler.java:883)
    at android.os.Handler.dispatchMessage(Handler.java:100)
    at android.os.Looper.loop(Looper.java:214)
    at android.app.ActivityThread.main(ActivityThread.java:7356)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
2021-01-27 22:54:48.053 1967-2079/system_process E/InputDispatcher: channel 'b8064d4 com.dbtest.VegJanv20211/com.dbtest.VegJanv20211.SearchActivity (server)' ~ Channel is unrecoverably broken and will be disposed!
2021-01-27 22:54:48.055 1967-2079/system_process E/InputDispatcher: channel '1b19412 com.dbtest.VegJanv20211/com.dbtest.VegJanv20211.MainActivity (server)' ~ Channel is unrecoverably broken and will be disposed!
2021-01-27 22:54:49.436 2609-3310/com.google.android.gms.persistent E/ModuleIdSetter: exception when setting module id
    java.lang.IllegalStateException: Unable to get current module info in ModuleManager created with non-module Context
        at com.google.android.chimera.config.ModuleManager.getCurrentModule(:com.google.android.gms@[email protected] (040700-319035315):2)
        at aewd.a(:com.google.android.gms@[email protected] (040700-319035315):4)
        at aewg.b(:com.google.android.gms@[email protected] (040700-319035315):9)
        at aeso.a(Unknown Source:0)
        at rpm.a(:com.google.android.gms@[email protected] (040700-319035315):0)
        at rlv.c(:com.google.android.gms@[email protected] (040700-319035315):1)
        at rlt.b(:com.google.android.gms@[email protected] (040700-319035315):1)
        at rok.b(:com.google.android.gms@[email protected] (040700-319035315):6)
        at rok.c(:com.google.android.gms@[email protected] (040700-319035315):6)
        at rok.b(:com.google.android.gms@[email protected] (040700-319035315):10)
        at rok.a(:com.google.android.gms@[email protected] (040700-319035315):17)
        at rok.g(:com.google.android.gms@[email protected] (040700-319035315):3)
        at sdr.a(:com.google.android.gms@[email protected] (040700-319035315):2)
        at scr.a(:com.google.android.gms@[email protected] (040700-319035315):10)
        at sci.a(:com.google.android.gms@[email protected] (040700-319035315):0)
        at scl.handleMessage(:com.google.android.gms@[email protected] (040700-319035315):28)
        at android.

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The problem's this line at the top of your error log:

kotlin.TypeCastException: null cannot be cast to non-null type androidx.appcompat.widget.SearchView

which is talking about this (which you mentioned is where it's crashing):

val searchView : SearchView = search?.actionView as SearchView

So you're trying to cast the result of the expressionsearch?.actionView (which can be null, you're null-checking it after all) to a non-null SearchView type. You're effectively telling the compiler "don't worry, this is definitely not going to be null!" but sometimes it is, and that's why the app is crashing - you're trying to cast null to a type that can't be null.

So you need to make searchView nullable, i.e. the type needs to be SearchView? not SearchView:

val searchView : SearchView? = search?.actionView as SearchView?

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...