如何修复代码以在Android App中从Fragment调用Activity?

问题描述 投票:-1回答:1

我想做什么

我想从Fragment调用Activity,以在Android应用程序中同时实现片段和活动之间的转换。

我已经成功地从片段文件中调用了活动文件上的一种特定方法,但是在从片段中调用整个活动时遇到了麻烦。

每页的基本功能

SampleFragment - MainActivity's fragmentMethod() is called once  the button is clicked on the page
Sample1Fragment - FormActivity is called once the button is clicked on the page
FormActivity - FormActivity2 is called once the button is clicked on the page

错误和问题

Sample1Fragment.kt上,我试图在下面调用整个FormActivity。

但是显示了错误消息,但我不知道要修复它以调用整个活动,而不是调用活动的方法。

Unresolved reference: AppCompatActivity

我尝试从Sample1Fragment调用FromActivity的部分

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        btnClick2.setOnClickListener(object:View.OnClickListener{

            // here I would like to move to FormActivity
            override fun onClick(v: View?) {
                (activity as FormActivity).AppCompatActivity()
            }

        })
    }

当前代码

MainActivity.kt

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Toast
import androidx.fragment.app.Fragment
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        // make the list of fragment
        val fragmentList = arrayListOf<Fragment>(
            SampleFragment(),
            Sample1Fragment()
        )

        // create instance of adapter
        val adapter = SamplePagerAdapter(supportFragmentManager, fragmentList)
        /// set adapter
        viewPager.adapter = adapter
    }



    public fun fragmentMethod() {
        Toast.makeText(this@MainActivity, "Method called From Fragment", Toast.LENGTH_LONG).show();
    }
}

SamileFragment.kt

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import kotlinx.android.synthetic.main.fragment_sample.*

class SampleFragment : Fragment() {


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        arguments?.let {

        }
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_sample, container, false)
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        btnClick.setOnClickListener(object:View.OnClickListener{
            override fun onClick(v: View?) {
                (activity as MainActivity).fragmentMethod()
            }

        })
    }



}

Sample1Fragment.kt

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import kotlinx.android.synthetic.main.fragment_sample1.*

class Sample1Fragment : Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_sample1, container, false)
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        btnClick2.setOnClickListener(object:View.OnClickListener{

            // here I would like to move to FormActivity
            override fun onClick(v: View?) {
                (activity as FormActivity).AppCompatActivity()
            }

        })
    }

}

SamplePagerAdapter.kt

import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentStatePagerAdapter

class SamplePagerAdapter(fm: FragmentManager, private val fragmentList: List<Fragment>) :
    FragmentStatePagerAdapter(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {

    // control fragment to show
    override fun getItem(position: Int): Fragment {
        return fragmentList[position]
    }

    // the size of contents(fragment list) to set viewPager
    override fun getCount(): Int {
        return fragmentList.size
    }
}

FormActivity.kt

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.app.Activity
import android.content.Intent
import android.util.Log
import kotlinx.android.synthetic.main.activity_form.*

class FormActivity : AppCompatActivity() {

    companion object {
        const val EXTRA_MESSAGE = "com.example.kotlinactivitydatatrans.MESSAGE"
    }

    private val RESULT_SUBACTIVITY = 1000

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

        button.setOnClickListener {
            if (editText.text != null) {
                val intent = Intent(applicationContext, FormActivity2::class.java)
                val str = editText.text.toString()
                Log.d("debug",str)

                intent.putExtra(EXTRA_MESSAGE, str)
                startActivityForResult(intent, RESULT_SUBACTIVITY)

                editText.setText("")

            }
        }
    }

    // to get a result form SubActivity
    override fun onActivityResult(requestCode: Int, resultCode: Int, intent: Intent?) {
        super.onActivityResult(requestCode, resultCode, intent)

        if (resultCode == Activity.RESULT_OK &&
            requestCode == RESULT_SUBACTIVITY && intent != null) {

            val res = intent.extras?.getString(EXTRA_MESSAGE)?: ""
            textView.text = res
        }
    }
}

我现在可以做什么

我可以从SampleFragment调用MainActivity.fragmentMethod(),并使用以下参考在SampleFragment和Sample1Fragment之间进行转换。

参考:Kotlin-How to call an activity method from fragment in Android App?

screen1screen2

开发环境

Android Studio 3.6.1

阅读评论后我试图做什么

新问题

成功构建了一个项目并在模拟器上运行该应用程序。但是,当我单击按钮以调用Sample1Fragment上的FormActivity时,屏幕突然关闭。

代码没有错误,所以我找不到任何解决方案。

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.example.fragact">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
            <activity android:name=".FormActivity"
            android:label="@string/app_name"
            tools:ignore="WrongManifestParent">
            </activity>
            <activity android:name=".FormActivity2"
                android:label="@string/app_name"
                tools:ignore="WrongManifestParent">
            </activity>
    </application>
</manifest>

fragment_sample1.xml

<FrameLayout 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"
        tools:context=".Sample1Fragment">

    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="32dp"
        android:text="Sample1Fragment"
        android:textSize="36sp" />

    <Button
            android:id="@+id/btnClick2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:layout_gravity="center"
            android:background="@color/colorPrimary"
            android:textColor="#FFF"
            android:textAllCaps="false"
            android:minEms="8"
            android:text="Call Activity"/>

    </FrameLayout>

Logcat

2020-03-10 18:50:48.622 9917-9917/com.example.fragact W/ActivityThread: handleWindowVisibility: no activity for token android.os.BinderProxy@f79aa98
2020-03-10 20:50:48.659 9917-9917/com.example.fragact D/AndroidRuntime: Shutting down VM
2020-03-10 20:50:48.661 9917-9917/com.example.fragact E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.fragact, PID: 9917
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.fragact/com.example.fragact.FormActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.Button.setOnClickListener(android.view.View$OnClickListener)' on a null object reference
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2913)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:6669)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
     Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.Button.setOnClickListener(android.view.View$OnClickListener)' on a null object reference
        at com.example.fragact.FormActivity.onCreate(FormActivity.kt:22)
        at android.app.Activity.performCreate(Activity.java:7136)
        at android.app.Activity.performCreate(Activity.java:7127)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2893)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048) 
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78) 
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108) 
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808) 
        at android.os.Handler.dispatchMessage(Handler.java:106) 
        at android.os.Looper.loop(Looper.java:193) 
        at android.app.ActivityThread.main(ActivityThread.java:6669) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858) 
2020-03-10 20:50:48.679 9917-9917/com.example.fragact I/Process: Sending signal. PID: 9917 SIG: 9
android android-fragments kotlin android-activity android-fragmentactivity
1个回答
0
投票

我认为这里的问题是您试图过早设置onClick侦听器。与活动不同,片段具有不同的生命周期,而且当View尚未创建(或已经销毁)时,情况也更容易获得。

查看this文档以获取更多信息。

[通常-开始与视图进行交互的最佳方法是onViewCreated生命周期回调。在这里以及之后,您可以确定视图层次结构已准备就绪。

在您的示例中,您已经使用onActivityCreated回调开始与视图进行交互。特别是,在btnClick.setOnClickListener(...)中设置onClick侦听器-SampleFragment。我认为在第一个片段中,它运作良好是因为它的创建与活动创建是“一致的”。

但是对于第二个片段-Sample1Fragment-活动已经创建,这可能导致错误的方法排序。我假设onActivityCreatedonViewCreated之前(在onCreateView上)被调用。并调用btnClick2.setOnClickListener(...)导致崩溃,原因是btnClick2尚未初始化。

我的建议是将片段的与视图相关的代码移到onViewCreated方法中。有这样的事情:

override fun onViewCreated(view: View, savedInstanceState: Bundle) {
    btnClick2.setOnClickListener(...)
}
© www.soinside.com 2019 - 2024. All rights reserved.