Kotlin Android rozpoczyna nową aktywność


104

Chcę rozpocząć inną aktywność na Androidzie, ale pojawia się ten błąd:

Proszę określić wywołanie konstruktora; klasyfikator „Strona 2” nie ma obiektu towarzyszącego

po utworzeniu instancji Intentklasy. Co mam zrobić, aby poprawić błąd? Mój kod:

class MainActivity : AppCompatActivity() {

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

    fun buTestUpdateText2 (view: View) {
        val changePage = Intent(this, Page2) 
        // Error: "Please specify constructor invocation; 
        // classifier 'Page2' does not have a companion object"

        startActivity(changePage)
    }

}

@BakaWaii ta strona już nie istnieje.
Scre

Odpowiedzi:


179

Aby uruchomić Activityw Javie, który napisaliśmy Intent(this, Page2.class), w zasadzie musisz zdefiniować Contextw pierwszym parametrze, a klasę docelową w drugim parametrze. Zgodnie z Intentmetodą w kodzie źródłowym -

 public Intent(Context packageContext, Class<?> cls)

Jak widać, Class<?>w drugim parametrze musimy podać typ.

Pisząc Intent(this, Page2), nigdy nie określamy, że przejdziemy klasę, staramy się przekazać classtyp, który jest niedopuszczalny.

Użyj, ::class.javaktóra jest alternatywą .classw kotlin. Użyj poniższego kodu, aby rozpocząćActivity

Intent(this, Page2::class.java)

Przykład -

val intent = Intent(this, NextActivity::class.java)
// To pass any data to next activity
intent.putExtra("keyIdentifier", value)
// start your next activity
startActivity(intent)

4
Masz jakiś pomysł, dlaczego zmienili to na ::class.javazamiast .class? Podejście Kotlin jest niezwykle skomplikowane w porównaniu z Javą.
Mr-IDE

3
@ Mr-IDE classzwraca Kotlin KClass, ale Android oczekuje Java Class<...>, stąd .javawłaściwość.
kirbyfan64sos

34

Po prostu można rozpocząć Activityw KOTLINtą metodą prostą,

val intent = Intent(this, SecondActivity::class.java)
intent.putExtra("key", value)
startActivity(intent)

1
Nie musisz używać metody putExtra, aby rozpocząć nową aktywność.
ShadeToD

@ShadeToD Yeah! Nie ma potrzeby używania putExtrametody. Po prostu dodałem go do przekazywania wartości podczas rozpoczynania nowegoActivity
Gowtham Subramaniam

31

Aby rozpocząć nową aktywność,

startActivity(Intent(this@CurrentClassName,RequiredClassName::class.java)

Więc zmień swój kod na:

class MainActivity : AppCompatActivity() {

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

    fun buTestUpdateText2 (view: View) {
        startActivity(Intent(this@MainActivity,ClassName::class.java))

        // Also like this 

        val intent = Intent(this@MainActivity,ClassName::class.java)
        startActivity(intent)
    }

2
this @ Activity jest równe Java's Activity.this :)
leoelstin

12

Generalnie można uprościć specyfikację parametru BlahActivity::class.java, definiując wbudowaną, reifikowaną funkcję ogólną.

inline fun <reified T: Activity> Context.createIntent() =
    Intent(this, T::class.java)

Ponieważ to na to pozwala

startActivity(createIntent<Page2>()) 

Albo jeszcze prostsze

inline fun <reified T: Activity> Activity.startActivity() {
    startActivity(createIntent<T>()) 
} 

Więc to teraz

startActivity<Page2>() 

Jako nowicjusz w kotlin, w jaki sposób umieścisz zmienną liczbę (lub żadną) funkcji putExtra () z tym?
Scre

1
Możesz ustawić inline fun <reified T: Activity> Context.createIntent(vararg extras: Pair<String, Any?>) = Intent(this, T::class.java).apply { putExtras(bundleOf(*extras)) }zamiast tego, co powiedziałem i zadziała (zakładając, że masz bundleOfz android-ktx lub anko)
EpicPandaForce

10

Musisz podać drugi argument typu klasy. Możesz też trochę uporządkować, jak poniżej.

startActivity(Intent(this, Page2::class.java).apply {
    putExtra("extra_1", value1)
    putExtra("extra_2", value2)
    putExtra("extra_3", value3)
})

7

Spróbuj tego

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

6

To jest moja główna działalność, w której nazwa użytkownika i hasło są przenoszone z edycji tekstu i ustawień do celu

class MainActivity : AppCompatActivity() {
val userName = null
val password = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
button.setOnClickListener {
    val intent = Intent(this@MainActivity,SecondActivity::class.java);
    var userName = username.text.toString()
    var password = password_field.text.toString()
    intent.putExtra("Username", userName)
    intent.putExtra("Password", password)
    startActivity(intent);
 }
}

To moja druga aktywność, w której muszę otrzymać wartości z głównej działalności

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_second)
var strUser: String = intent.getStringExtra("Username")
var strPassword: String = intent.getStringExtra("Password")
user_name.setText("Seelan")
passwor_print.setText("Seelan")
}

4

Dzieje się tak, ponieważ Twoja Page2klasa nie ma obiektu towarzyszącego, który jest podobny do tego staticw Javie, więc aby użyć swojej klasy. Aby przekazać swoją klasę jako argument Intent, będziesz musiał zrobić coś takiego

val changePage = Intent(this, Page2::class.java)

4

Od aktywności do aktywności

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

Od fragmentu do działania

val intent = Intent(activity, YourActivity::class.java)
startActivity(intent)

4

Cóż, znalazłem te 2 sposoby na najprostsze ze wszystkich wyników:

Sposób nr 1:

accoun_btn.setOnClickListener {
            startActivity(Intent(this@MainActivity, SecondActivity::class.java))
        }

Sposób 2: (w ogólny sposób)

    accoun_btn.setOnClickListener {
        startActivity<SecondActivity>(this)
    }

    private inline fun <reified T> startActivity(context: Context) {
            startActivity(Intent(context, T::class.java))
        }

próba


1
val intentAct: Intent = Intent(this@YourCurrentActivity, TagentActivity::class.java)
startActivity(intentAct)

1

Miałem podobny problem, zacząłem pisać aplikację w Kotlinie, po przepisaniu jednej z moich czynności chciałem sprawdzić, czy są jakieś problemy, problem polegał na tym, że nie byłem pewien jak wysłać intencję z pliku java do kotlina plik.

W tym przypadku utworzyłem statyczną funkcję w kotlin (obiekt towarzyszący), ta funkcja pobiera kontekst (z bieżącej czynności) i zwraca nową intencję podczas korzystania z bieżącego kontekstu (kontekst "java") podczas używania klasy kotlin (" :: class.java ”).

Oto mój kod:

 //this code will be in the kotlin activity - SearchActivity
 companion object {

    fun newIntent(context: Context): Intent {
        return Intent(context, SearchActivity::class.java)
    }
}

    //this is how you call SearchActivity from MainActivity.java
Intent searchIntent = SearchActivity.Companion.newIntent(this);
startActivity(searchIntent);

Jeśli dodasz @JvmStaticdo swojej newIntentmetody, możesz wywołać ją z javy bez Companionczęści.
Wirling

0

Detale

  • Android Studio 3.1.4
  • Wersja Kotlin: 1.2.60

Krok 1. Aplikacja ()

Uzyskaj link do kontekstu swojej aplikacji

class MY_APPLICATION_NAME: Application() {

    companion object {
        private lateinit var instance: MY_APPLICATION_NAME
        fun getAppContext(): Context = instance.applicationContext
    }

    override fun onCreate() {
        instance = this
        super.onCreate()
    }

}

Krok 2. Dodaj obiekt routera

object Router {
    inline fun <reified T: Activity> start() {
         val context =  MY_APPLICATION_NAME.getAppContext()
         val intent = Intent(context, T::class.java)
         context.startActivity(intent)
    }
}

Stosowanie

// You can start activity from any class: form Application, from any activity, from any fragment and other  
Router.start<ANY_ACTIVITY_CLASS>()

0

Pamiętaj, aby dodać aktywność, którą chcesz zaprezentować, również do swojej AndroidManifest.xml:-) To był problem dla mnie.


0

Co powiesz na rozważenie hermetyzacji?

Na przykład:


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

        val title = intent.getStringExtra(EXTRA_TITLE) ?: EXTRA_TITLE_DEFAULT

        supportFragmentManager.beginTransaction()
            .add(R.id.frame_layout_fragment, ContentsFragment.newInstance())
            .commit()
    }

    // Omit...

    companion object {

        private const val EXTRA_TITLE = "extra_title"
        private const val EXTRA_TITLE_DEFAULT = "No title"

        fun newIntent(context: Context, title: String): Intent {
            val intent = Intent(context, ContentsActivity::class.java)
            intent.putExtra(EXTRA_TITLE, title)
            return intent
        }
    }

0

W swojej aplikacji możesz używać zarówno plików Kotlin, jak i Java.

Aby przełączać się między tymi dwoma plikami, upewnij się, że w pliku AndroidManifest.xml podajesz im unikalne <action android: name = "", na przykład:

            <activity android:name=".MainActivityKotlin">
                <intent-filter>
                    <action android:name="com.genechuang.basicfirebaseproject.KotlinActivity"/>
                    <category android:name="android.intent.category.DEFAULT" />
                    <action android:name="android.intent.action.MAIN" />
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
            <activity
                android:name="com.genechuang.basicfirebaseproject.MainActivityJava"
                android:label="MainActivityJava" >
                <intent-filter>
                    <action android:name="com.genechuang.basicfirebaseproject.JavaActivity" />
                    <category android:name="android.intent.category.DEFAULT" />
                </intent-filter>
            </activity>

Następnie w pliku MainActivity.kt (plik Kotlin), aby rozpocząć działanie napisane w języku Java, wykonaj następujące czynności:

       val intent = Intent("com.genechuang.basicfirebaseproject.JavaActivity")
        startActivity(intent)

W pliku MainActivityJava.java (plik Java), aby rozpocząć działanie napisane w Kotlin, wykonaj następujące czynności:

       Intent mIntent = new Intent("com.genechuang.basicfirebaseproject.KotlinActivity");
        startActivity(mIntent);

0

Innym prostym sposobem na przejście do innej czynności jest

Intent(this, CodeActivity::class.java).apply {
                    startActivity(this)
                }

1
Pls rozważ wyjaśnienie swojego kodu i tego, w jaki sposób może to pomóc, aby inni mogli z tego skorzystać.
Amit Verma
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.