Android Intent-Handling zwischen Aktivitäten mit Kotlin

In diesem Tutorial werden wir über Android-Intents diskutieren und sie mit Kotlin in unserer Anwendung implementieren.

Was lernst du?

  • Was sind Intents?
  • Arten von Intents?
  • Verwendung von Intents zwischen Aktivitäten
  • Daten senden mit Android Intents
  • Verwendung von Parcelable und Serializable zur Übermittlung von Objekten
  • Erstellen von Kurzintents

Android Intents

Wie der Name schon sagt, ist Intent etwas, das verwendet wird, um eine Aktion im Zusammenhang mit dem Ablauf der Android-Anwendung auszuführen. Intents können verwendet werden, um:

  • Starten einer neuen Aktivität und Übergeben von Daten.
  • Starten von Fragments/Kommunikation zwischen Fragments.
  • Start/Beenden von Diensten.
  • Starten von Aktivitäten aus einem Broadcast-Empfänger

In diesem Tutorial werden wir uns hauptsächlich mit Intents befassen, um Aktivitäten zu behandeln. Eine Intent-Definition besteht hauptsächlich aus einer Instanz der aktuellen Aktivität. Wir setzen den Komponentennamen, der sein kann: Der vollqualifizierte Klassenname der aufzurufenden Aktivität. Diese Art von Intent ist ein expliziter Intent. Eine Aktion wie URL, Telefonnummer, Ort. Es werden alle verfügbaren Anwendungen dieser Art angezeigt. Dies fällt in die Kategorie impliziter Intent. In Kotlin ist folgendes die Möglichkeit, eine Aktivität zu erstellen.

val intent = Intent(this, OtherActivity::class.java)
startActivity(intent)

startActivity würde OtherActivity auf den Aktivitätsstapel hinzufügen und starten. Wie erkennt unsere Anwendung, welche Aktivität zuerst aufgerufen wird? Im AndroidManifest.xml setzen wir den Intent-Filter mit der Aktion android.intent.action.MAIN und der Kategorie android.intent.category.LAUNCHER auf der ersten Aktivität, die beim Öffnen unserer Anwendung gestartet wird. finish() wird verwendet, um eine Aktivität zu zerstören und sie aus dem Stapel zu entfernen.

Intent-Flags

Flags sind wie Optionen, die auf Intents gesetzt werden können, um den Startvorgang anzupassen. Wenn Sie jedes Mal dieselbe Aktivität starten, wird eine neue Instanz erstellt und dem Aktivitätsstapel hinzugefügt. Um dies zu verhindern, können Sie die Flags verwenden: FLAG_ACTIVITY_SINGLE_TOP – Wenn festgelegt, wird die Aktivität nicht gestartet, wenn sie bereits oben im Aktivitätsstapel läuft.

intent.flags = Intent.FLAG_ACTIVITY_SINGLE_TOP

Ebenso würde die Verwendung eines Flags FLAT_ACTIVITY_CLEAR_TOP keine weitere Instanz der Aktivität starten, wenn sie bereits existiert. Dieses Flag würde alle Aktivitäten über der aufgerufenen Aktivität löschen und sie oben auf den Stapel setzen.

Datenübermittlung durch Intents

Um Daten an neue Aktivitäten weiterzugeben, verwenden wir Schlüssel-Wert-Paare innerhalb der Funktion putExtra, putStringArrayListExtra usw. putExtra gibt im Allgemeinen grundlegende Typen wie Int, Float, Char, Double, Boolean, String sowie IntArray… usw. weiter.

val intent = Intent(this, OtherActivity::class.java)
intent.putExtra("keyString", "Androidly String data")

Diese Extras-Felder werden intern in das Bundle-Objekt eingefügt, das letztendlich alle zu übergebenden Daten enthält. Um die Daten in der anderen Aktivität abzurufen, müssen wir die extras-Eigenschaft über den bundle-Objekten verwenden. Abrufen von Daten in der neuen Aktivität

val bundle: Bundle? = intent.extras
val string: String? = intent.getString("keyString")
val myArray: ArrayList<String>? = intent.getStringArrayList("myArray")

intent, extras entsprechen getIntent(), getExtras() in Java. Wir haben einen nullable Typ Bundle? verwendet, um NullPointerExceptions zu verhindern, wenn keine Daten vorhanden sind. Ebenso haben wir für die abgerufenen Daten, die mithilfe der Schlüssel erfolgen, nullable Typen verwendet, um NPE zu verhindern, die auftreten können, wenn der Schlüssel falsch ist.

Verwendung von Parcelable und Serializable Daten

Manchmal müssen wir ein vollständiges Objekt von einer Aktivität zur anderen übergeben. Dies ist nur möglich, wenn wir das Parcelable- oder Serializable-Interface implementieren. Unterschied zwischen Parcelable und Serializable

  • Das Parcelable-Interface ist ein Teil des Android SDK. Serializable ist ein Standardinterface von Java.
  • In Parcelable müssen Sie alle Daten, die Sie übergeben möchten, in ein Parcel-Objekt setzen und auch die writeToParcel()-Methoden usw. überschreiben. Bei Serializable reicht es aus, das Interface zu implementieren, um die Daten zu übergeben.
  • Parcelable ist schneller als Serializable.

Senden von Parcelable-Daten

Kotlin kommt mit einigen praktischen Annotationen, um uns vor dem Überschreiben der writeToParcel()-Methode zur Festlegung der Daten auf dem Parcelable zu bewahren. Stattdessen können wir die @Parcelize-Annotation wie unten gezeigt verwenden:

@Parcelize
data class Student(
        val name: String = "Anupam",
        val age: Int = 24
) : Parcelable

Hinweis: Aktuell müssen Sie in Ihrer build.gradle den folgenden Code für die @Parcelize-Annotation hinzufügen, damit sie funktioniert:

android {
    androidExtensions {
        experimental = true
    }
//..
....
}

In Ihrer Aktivität machen Sie folgendes:

val student = Student()
val intent = Intent(this, OtherActivity::class.java)
intent.putExtra("studentData", student)
startActivity(intent)

Senden von Serializable-Daten

data class Blog(val name: String = "Androidly", val year: Int = 2018) : Serializable

val blog = Blog("a", 1)
val intent = Intent(this, OtherActivity::class.java)
intent.putExtra("blogData", blog as Serializable)
startActivity(intent)

Lassen Sie uns unser Wissen in unserem Android-Studio-Projekt anwenden.

Projektstruktur

Layout Code

Der Code für das Layout activity_main.xml ist wie folgt:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/btnSimpleIntent"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="SIMPLE INTENT" />


    <Button
        android:id="@+id/btnSimpleIntentAndData"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="SIMPLE INTENT WITH DATA" />


    <Button
        android:id="@+id/btnParcelableIntent"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Parcelable Intent" />


    <Button
        android:id="@+id/btnSerializableIntent"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Serializable Intent" />

    <Button
        android:id="@+id/btnBrowserIntent"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Browser Intent" />


    <Button
        android:id="@+id/btnMapsIntent"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Maps Intent" />


    <Button
        android:id="@+id/btnGenericIntent"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Generic Intent" />

</LinearLayout>

Der Code für das Layout activity_other.xml ist wie folgt:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Intent Data goes here" />


</LinearLayout>

Activity Code

Der Code für die Klasse MainActivity.kt ist wie folgt:

package net.androidly.androidlyintents

import android.app.Activity
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.os.Parcelable
import android.view.View
import android.widget.Toast
import android.widget.Toast.LENGTH_LONG
import kotlinx.android.parcel.Parcelize
import kotlinx.android.synthetic.main.activity_main.*
import java.io.Serializable


@Parcelize
data class Student(
        val name: String = "Anupam",
        val age: Int = 24
) : Parcelable

data class Blog(val name: String = "Androidly", val year: Int = 2018) : Serializable


class MainActivity : AppCompatActivity(), View.OnClickListener {


    fun Context.gotoClass(targetType: Class<*>) =
            ComponentName(this, targetType)

    fun Context.startActivity(f: Intent.() -> Unit): Unit =
            Intent().apply(f).run(this::startActivity)

    inline fun <reified T : Activity> Context.start(
            noinline createIntent: Intent.() -> Unit = {}
    ) = startActivity {
        component = gotoClass(T::class.java)
        createIntent(this)
    }


    var arrayList = ArrayList<String>()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        btnSimpleIntent.setOnClickListener(this)
        btnSimpleIntentAndData.setOnClickListener(this)
        btnParcelableIntent.setOnClickListener(this)
        btnSerializableIntent.setOnClickListener(this)
        btnBrowserIntent.setOnClickListener(this)
        btnMapsIntent.setOnClickListener(this)
        btnGenericIntent.setOnClickListener(this)

        arrayList.add("Androidly")
        arrayList.add("Android")
        arrayList.add("Intents")
    }

    override fun onClick(v: View?) {
        when (v?.id) {
            R.id.btnSimpleIntent -> {
                val intent = Intent(this, OtherActivity::class.java)
                startActivity(intent)
            }
            R.id.btnSimpleIntentAndData -> {
                val intent = Intent(this, OtherActivity::class.java)
                with(intent)
                {
                    putExtra("keyString", "Androidly String data")
                    putStringArrayListExtra("arrayList", arrayList)
                    putExtra("keyBoolean", true)
                    putExtra("keyFloat", 1.2f)
                }
                startActivity(intent)
            }
            R.id.btnParcelableIntent -> {

                val student = Student()
                val intent = Intent(this, OtherActivity::class.java)
                intent.putExtra("studentData", student)
                startActivity(intent)
            }
            R.id.btnSerializableIntent -> {
                val blog = Blog("a", 1)
                val intent = Intent(this, OtherActivity::class.java)
                intent.putExtra("blogData", blog as Serializable)
                startActivity(intent)
            }
            R.id.btnBrowserIntent -> {
                val url = "https://www.androidly.net"
                val uri = Uri.parse(url)
                val intent = Intent(Intent.ACTION_VIEW, uri)

                if (intent.resolveActivity(packageManager) != null) {
                    startActivity(intent)
                } else {
                    Toast.makeText(applicationContext, "No application found", LENGTH_LONG).show()
                }
            }
            R.id.btnMapsIntent -> {
                val loc = "12.9538477,77.3507442"

                val addressUri = Uri.parse("geo:0,0?q=" + loc)
                val intent = Intent(Intent.ACTION_VIEW, addressUri)


                if (intent.resolveActivity(packageManager) != null) {
                    startActivity(intent)
                } else {
                    Toast.makeText(applicationContext, "No application found", LENGTH_LONG).show()
                }
            }
            else -> start<OtherActivity> {
                putExtra("keyString", "Androidly Generic Intent")
            }
        }
    }

}

In dem oben stehenden Code haben wir Buttons für jeden Typ von Intent verwendet. Wir haben den with-Ausdruck von Kotlin verwendet, um Daten nicht jedes Mal über das intent-Objekt zu setzen. Außerdem haben wir drei verschiedene Intents erstellt, zusätzlich zu denen, die bereits besprochen wurden. Ein Browser-Intent wird verwendet, um die URL im Intent im Browser zu öffnen. Es verwendet Intent(Intent.ACTION_VIEW, uri). Ein Standort-Intent wird verwendet, um die Lat, Lng-Position in der Kartenanwendung zu öffnen. Beide sind implizite Intents. Schließlich haben wir einen generischen Intent verwendet, für den wir die Erweiterungsfunktionen von Kotlin und Lambda-Ausdrücke verwenden, um eine Shorthand-Funktion zum Starten eines Intents zu erstellen. Hierfür verwenden wir die folgenden Funktionen:

fun Context.gotoClass(targetType: Class<*>) =
            ComponentName(this, targetType)

    fun Context.startActivity(createIntent: Intent.() -> Unit): Unit =
            Intent().apply(createIntent).run(this::startActivity)

    inline fun <reified T : Activity> Context.start(
            noinline createIntent: Intent.() -> Unit = {}
    ) = startActivity {
        component = gotoClass(T::class.java)
        createIntent(this)
    }

startActivity ist eine Erweiterungsfunktion, die nach einer Funktion höherer Ordnung als Parameter sucht. Dank dessen können wir jetzt Intents in so wenigen Zeilen wie möglich starten: start<OtherActivity> Der Code für die Klasse OtherActivity.kt ist unten angegeben.

package net.androidly.androidlyintents

import android.content.Context
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.widget.Toast
import kotlinx.android.synthetic.main.activity_other.*

class OtherActivity : AppCompatActivity() {


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_other)

        val bundle: Bundle? = intent.extras

        bundle?.let {

            bundle.apply {
                //Intent mit Daten
                val string: String? = getString("keyString")
                textView.text = string

                val myArray: ArrayList? = getStringArrayList("myArray")
                showToast(message = "MyArrayList size:${myArray?.size}")

                val arrayList: ArrayList? = getStringArrayList("arrayList")
                showToast(message = "ArrayList size:${arrayList?.size}")

                val float: Float? = bundle.get("keyFloat") as Float?
                var boolean = bundle.get("boolean") as? Boolean

                showToast(message = "Float data is:$float")
                showToast(message = "Boolean data is:$boolean")
                boolean = bundle.get("keyBoolean") as? Boolean
                showToast(message = "Boolean correct key data is:$boolean")

            }



            bundle.apply {
                //Serializable Daten
                val blog = getSerializable("blogData") as Blog?
                if (blog != null) {
                    textView.text = "Blog name is ${blog?.name}. Year started: ${blog?.year}"

                }
            }

            bundle.apply {
                //Parcelable Daten
                val student: Student? = getParcelable("studentData")
                if (student != null) {
                    textView.text = "Name is ${student?.name}. Age: ${student?.age}"
                }
            }
        }
    }

    private fun showToast(context: Context = applicationContext, message: String, duration: Int = Toast.LENGTH_SHORT) {
        if (!message.contains("null"))
            Toast.makeText(context, message, duration).show()
    }
}

Wir haben `let` und `apply` verwendet, um mit `nullable` Typen umzugehen und das Ausführen von `bundle.field` in jeder Zeile zu verhindern. Die Ausgabe der obigen Anwendung in Aktion ist unten angegeben: Damit endet dieses Tutorial zu Android-Intents in Kotlin. Sie können das Projekt über den untenstehenden Link herunterladen.

AndroidlyIntents

Source:
https://www.digitalocean.com/community/tutorials/android-intent-handling-between-activities-using-kotlin