[JAVA] Über Smart Cast im Rückruf von Fragment zu Aktivität in Kotlin

Einführung

Während der Migration einer vorhandenen Android-Anwendung von Java nach Kotlin war ich süchtig danach, Listener (Schnittstelle) in Fragment zu implementieren und Code zu schreiben, der ein Ereignis aufruft, wenn eine UI-Operation ausgeführt wird, also ein Memo zu diesem Zeitpunkt.

Umgebung

Was ich versucht habe zu tun

Definieren Sie einen Listener, der von Activity auf der Fragment-Seite aufgerufen werden soll, wandeln Sie den Kontext in Listener um, wenn der Argumentkontext beim Aufrufen der onAttach-Methode eine Schnittstelle implementiert, und rufen Sie die Ereignismethode der Activity auf, wenn die Schaltfläche gedrückt wird. Der folgende Java-Code Ich habe versucht, es in Kotlin umzuschreiben.

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()
            }
        }
    }

    //...
}

Wenn Sie dann mListener.onClickButton () aufrufen

Smart cast to 'MyFragment.FragmentListener’ is impossible, because 'mListener’ is a mutable property that could have been changed by this time

Ich bekomme eine Fehlermeldung.

Dies ist ein Fehler, bei dem die intelligente Umwandlung in FragmentListener nicht ausgeführt werden kann, da möglicherweise ein Umschreiben von einem anderen Thread erfolgt, weil "mListener" mit "var" deklariert ist.

Wenn Sie es jedoch mit "val" deklarieren, können Sie keinen Kontext zuweisen.

Lösung

Daher habe ich es dieses Mal gelöst, indem ich die Scope-Funktion let verwendet habe, ohne Smart Cast zu machen.

Vorher ändern


if (mListener != null){
	mListener.onClickButton()
}

Nach der veränderung


mListener?.let { it.onClickButton() }

Wenn mListener`` null ist, führt der? .calllet {}nicht aus, und wenn er nicht null ist, wird die Verarbeitung inlet {}ausgeführt.

In diesem Fall kann auch die folgende Beschreibung vorgenommen werden.


mListener?.let(FragmentListener::onClickButton)

Referenzmaterial

Kotlin Reference: Type Checks and Casts: 'is' and 'as'

Zusammenfassung der Verwendung der Kotlin-Bereichsfunktionen

[Android] Einführung in Kotlin für App-Ingenieure (Grundlegende Grammatik)

Recommended Posts

Über Smart Cast im Rückruf von Fragment zu Aktivität in Kotlin
Woran ich dachte, als ich anfing, von Java nach Kotlin zu migrieren
Versuchen Sie, mit MyBatis im Micronaut + Kotlin-Projekt Daten aus der Datenbank abzurufen
Eine Geschichte über das Konvertieren von Zeichencodes von UTF-8 in Shift-jis in Ruby
[Kotlin] Drei Möglichkeiten, um Klasse von KClass zu bekommen
Memo für die Migration von Java nach Kotlin
Zusammenfassung der Punkte, über die ich mir bei der Migration von Java nach Kotlin Sorgen gemacht habe