While migrating an existing Android application from Java to Kotlin, I was addicted to implementing Listener (interface) in Fragment and writing code that calls an event at the timing of UI operation, so a memo at that time.
Define a Listener to be called from Activity on the Fragment side, cast the context to Listener if the argument context implements interface when the onAttach method is called, and call the Activity event method when the button is pressed The following Java code I tried to rewrite it in Kotlin.
MyFragment.java
public class MyFragment extends Fragment {
public interface FragmentListener {
void onClickButton();
}
private FragmentListener mListener;
@Override
public void onAttach(Context context){
//...
if (context instanceof FragmentListener){
mListener = (FragmentListener) context;
}
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState){
//...
view.findViewById(R.id.Button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v){
if (mListener != null){
mListener.onClickButton();
}
}
});
}
//...
}
MyFragment.kt
class MyFragment : Fragment() {
interface FragmentListener {
fun onClickButton()
}
private var mListener: FragmentListener? = null
override fun onAttach(context: Context){
//...
if (context is FragmentListener){
mListener = context
}
}
override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
//...
view!!.findViewById<Button>(R.id.Button).setOnClickListener {
if (mListener != null){
mListener.onClickButton()
}
}
}
//...
}
Then, when you call mListener.onClickButton ()
Smart cast to 'MyFragment.FragmentListener’ is impossible, because 'mListener’ is a mutable property that could have been changed by this time
I get an error.
This is an error that smart cast to FragmentListener cannot be performed because rewriting from another thread may occur because mListener
is declared with var
.
However, if you declare it with val
, context cannot be assigned.
Therefore, this time, I solved it by using the scope function let
without doing smart cast.
Change before
if (mListener != null){
mListener.onClickButton()
}
After change
mListener?.let { it.onClickButton() }
If mListener
is null
, the ?.
call does not executelet {}
, and if it is not null
, the processing inside let {}
is executed.
In this case, the following description can also be made.
mListener?.let(FragmentListener::onClickButton)
Kotlin Reference: Type Checks and Casts: 'is' and 'as'
Summary of usage of Kotlin scope function
[Android] Introduction to Kotlin for App Engineers (Basic Grammar)
Recommended Posts