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
230 views
in Technique[技术] by (71.8m points)

android - Why is setting onClickListener working once?

I want to migrate a very solid project structure that I use to Kotlin. I first tried the basics: Activities and Fragment transactions. It appears so easy and simple:

class MainActivity : AppCompatActivity(), SomeInterface {
     override fun onCreate(savedInstanceState: Bundle?) {
         setContentView(R.layout.activity_main)

         val mainFragment = supportFragmentManager.findFragmentById(R.id.fragment_main) as MainActionsFragment?
                    ?: MainActionsFragment.newInstance()
         supportFragmentManager.inTransaction {
              add(R.id.container_main, mainFragment)
         }
    }

    private val anotherFragment by lazy {
    supportFragmentManager.findFragmentById(R.id.another_fragment) as AnotherFragment?
            ?: AnotherFragment.newInstance()
    }

    override fun myInterfaceMethod() {
        replaceFragment(anotherFragment, R.id.container_main)
    }
}

class MainActionsFragment : Fragment() {
    val btnSale: Button by bindView(R.id.btn_sale)
    val btnVisit: Button by bindView(R.id.btn_visit)

    override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return inflater!!.inflate(R.layout.fragment_main, container, false)
    }

    override fun onResume() {
        super.onResume()

        btnSale.setOnClickListener{ _ ->
            listener.requestAction(SaleType.SALE)
        }

        btnVisit.setOnClickListener{ _ ->
            listener.requestAction(SaleType.VISIT)
        }
    }
}

Extensions.kt

fun AppCompatActivity.replaceFragment(fragment: Fragment, @IdRes frameId: Int) {
    supportFragmentManager.inTransaction {
        replace(frameId, fragment)
                .addToBackStack(fragment.tag)
    }
}

inline fun FragmentManager.inTransaction(func: FragmentTransaction.() -> FragmentTransaction) {
    beginTransaction()
            .func()
            .commit()
}

Now, MainActionsFragment holds two buttons. Everything works as expected, the first click on either one takes me to the desired fragment. However, once I press the back button and I see my two buttons again, their click listener is gone. This is pretty much the standard way of doings things translated to Kotlin, nothing fancy besides its cool new features. I tried moving setting the onClickListeners to onCreateView() but it crashes:

Caused by: kotlin.KotlinNullPointerException at kotterknife.ButterKnifeKt$viewFinder$7.invoke(ButterKnife.kt:95) at kotterknife.ButterKnifeKt$viewFinder$7.invoke(ButterKnife.kt) at kotterknife.ButterKnifeKt$required$1.invoke(ButterKnife.kt:104) at kotterknife.ButterKnifeKt$required$1.invoke(ButterKnife.kt) at kotterknife.Lazy.getValue(ButterKnife.kt:125)

So, in spite of Kotlin being so cool, I'm having trouble doing the basics and I'm getting disheartened to migrate. Am I really doing things so wrong? Or how come setting a simple click listener is so frustrating?

Thank you.

See Question&Answers more detail:os

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

1 Reply

0 votes
by (71.8m points)

You have to set your variables that are bound by ButterKnife as lateinit var instead of val. Try

@BindView(R.id.btn_sale)
lateinit var title: Button

@BindView(R.id.btn_visit)
lateinit var title: Button

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

...