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

}
J Adonai Dagdag
źródło
@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)
Rahul
źródło
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)
Gowtham Subramaniam
źródło
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)
    }
leoelstin
źródło
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>() 
EpicPandaForce
źródło
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)
})
Adib Faramarzi
źródło
7

Spróbuj tego

val intent = Intent(this, Page2::class.java)
startActivity(intent)
Boris
źródło
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")
}
Bharat Vasoya
źródło
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)
Alf Moh
źródło
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)
Masum
źródło
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

Saadat Sayem
źródło
1
val intentAct: Intent = Intent(this@YourCurrentActivity, TagentActivity::class.java)
startActivity(intentAct)
Ashish Patel
źródło
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);
Anton Makov
źródło
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>()
Wasilij Bodnarczuk
źródło
0

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

Nicolai Harbo
źródło
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
        }
    }
libliboom
źródło
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);
Gen
źródło
0

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

Intent(this, CodeActivity::class.java).apply {
                    startActivity(this)
                }
Mohamed AbdelraZek
źródło
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