【问题标题】:How to fetch resource id in fragment using kotlin in android?如何在android中使用kotlin获取片段中的资源ID?
【发布时间】:2017-09-26 06:21:56
【问题描述】:

我尝试了下面提到的这段代码,但在运行时崩溃了。发生的错误是 Android Run time:

致命异常:主进程:com.root.specialbridge,PID:17706 kotlin.KotlinNullPointerException at com.root.specialbridge.fragments.profile_fragment.WallFragments.initializeView(WallFragments.kt:49)

class WallFragments : Fragment(){

private var wallAdapter: WallAdapter? = null
private var wall_recycler: RecyclerView? = null
private val wallArrayList: ArrayList<Wall>? = null
private var mainlayout: LinearLayout? = null
private var no_result_found_layout: RelativeLayout? = null
private var userProfileWallInterface: UserProfileWallInterface? = null
internal var wallActivityBeanse: MutableList<WallActivityBeans> = ArrayList()

override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    val view = inflater!!.inflate(R.layout.wall_fragments, container, false)
    userProfileWallInterface = UserProfileWallPresentation(activity, this)
    initializeView()
    wallAdapter = WallAdapter(activity, wallActivityBeanse)
    wall_recycler!!.adapter = wallAdapter

    return view
}
fun initializeView() {
    wall_recycler = view!!.findViewById(R.id.wall_recycler_id) as RecyclerView
    mainlayout = view!!.findViewById(R.id.mainlayout) as LinearLayout
    no_result_found_layout = view!!.findViewById(R.id.no_result_found_layout) as RelativeLayout
    wall_recycler!!.layoutManager = LinearLayoutManager(activity)
    wall_recycler!!.setHasFixedSize(true)
    if (AuthPreference(activity).isGetMemberProfile) {
        userProfileWallInterface!!.getMemberProfileWall(view!!)

    } else {
        userProfileWallInterface!!.getUserProfileWall(AuthPreference(activity).token, AuthPreference(activity).user.id, view!!)

    }
}   
companion object {
    val instance: WallFragments
        get() = WallFragments()  }}

【问题讨论】:

  • 您应该在onViewCreated() 中调用initializeView(),或者使用您膨胀的view 而不是view!!。调用getView() 将在onCreateView 返回之前返回null。看看这个question
  • @BakaWaii 你能举个例子吗,这会更有帮助谢谢
  • @Anchal Singh 我尝试使用全局变量,但遇到了智能转换问题。请帮我举个例子谢谢
  • @Vishal Vaishnav 你有答案吗

标签: android kotlin


【解决方案1】:

添加

apply plugin: 'kotlin-android-extensions'

在应用级别的 gradle 文件中和

导入

import kotlinx.android.synthetic.main.fragment_your_fragment_name.view.*

在您的片段的onCreateView 中(例如,如果您的 textview 的 id 是 textView)

override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {
    // Inflate the layout for this fragment
    val view = inflater!!.inflate(R.layout.fragment_splashfragment, container, false)
    view.textView.text = "hello"   //add your view before id else getting nullpointer exception
    return view
}

更新:

在你的类中声明 viewOfLayout 而不是 view。

class yourfragment:Fragment(){

    private lateinit var viewOfLayout: View
    override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {
        // Inflate the layout for this fragment
        viewOfLayout = inflater!!.inflate(R.layout.fragment_splashfragment, container, false)
        viewOfLayout.textView.text = "hello"   //add your view before id else will get nullpointer exception
        return viewOfLayout
    }

}

【讨论】:

  • 无需像Fragment 中的全局那样采用view。就像在 Activity 中一样,可以直接使用它的 id 访问视图元素。
  • 这个答案顶部的导入声明节省了我的时间,因此赞成!
  • @krishh 仅在执行 oncreateview 后
  • 是的@KiranBennyJoseph,这就是我们有onViewCreated() 方法的原因。
【解决方案2】:

介绍Kotlin Android Extensions

您不必再使用findViewById。使用此插件,您可以直接将 UI 组件用作全局字段。在Activitiesfragmentsviews 中受支持。

例如, 要从下面的布局中引用文本视图,

<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/hello"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="Hello World, MyActivity"/>

</android.support.constraint.ConstraintLayout>

在活动中你可以简单地写,

// Using R.layout.activity_main from the main source set
import kotlinx.android.synthetic.main.activity_main.*

class MyActivity : Activity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        // Instead of findViewById(R.id.hello) as TextView
        hello?.setText("Hello, world!")
    }
}

在片段中,

// Using R.layout.fragment_content from the main source set
import kotlinx.android.synthetic.main.fragment_content.*

class ContentFragment : Fragment() {

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? =
        inflater.inflate(R.layout.fragment_content, container, false)

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        // Instead of view.findViewById(R.id.hello) as TextView
        hello?.setText("Hello, world!")
    }
}

对于视图,

// Using R.layout.item_view_layout from the main source set
import kotlinx.android.synthetic.main.item_view_layout.*

class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) {

    fun bindData(data: String) {
        // Instead of itemView.findViewById(R.id.hello) as TextView
        itemView.hello?.setText(data)
    }

}

而且,您不应该在任何地方使用!!,除非您明确需要NullPointerException

请改用以下任何人:

  1. 使用安全调用进行空值检查 - ?.,例如。 nullableVariable?.method()
  2. 使用?.let{ } 使用非空对象,例如。 nullableVariable?.let { it.method() }
  3. 使用 elvis 运算符为可空变量提供备份值 - ?:,例如。 nullableVariable ?: &lt;backupValue&gt;.

阅读更多关于Null Safety in Kotlin的信息。

【讨论】:

  • 这是一个很好且方便的答案,但与问题中的问题完全无关。有关如何在活动中使用 kotlin android 扩展的信息传播广泛且易于查找。片段不是这样的
  • @Vendetta8247 与 Fragments 的情况相同。就像在活动中一样,您可以使用 id 直接访问视图。正确阅读我的答案。
  • 这难道不是旨在取代优雅简单、易于理解和灵活findViewById() 的宏伟设计扩展吗?
【解决方案3】:

片段中视图的初始化:

wall_recycler=view.findViewById<RecyclerView>(R.id.wall_recycler_id)
mainlayout = view.findViewById<LinearLayout>(R.id.mainlayout)

问题是您访问它太快了。 requireView()viewonCreateView 中返回 null。我在 onViewCreated() 中找到了所有视图。 尝试在onViewCreated 方法中执行此操作:

 override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {

 wall_recycler=requireView().findViewById<RecyclerView>(R.id.wall_recycler_id)
 mainlayout = requireView().findViewById<LinearLayout>(R.id.mainlayout)
 mainlayout.setOnClickListener { Log.d(TAG, "onViewCreated(): hello world");}
    }

【讨论】:

  • 你能分享一下你的 onCreateView 代码和作为全球视图的声明吗
  • 我已经更新了我的答案,如果可行,请选择它作为正确答案。
  • 您不需要在onViewCreated() 方法中调用getView()。你已经有view: View? 对象了。顺便说一句,如果@Ramesh 在onCreateView() 本身中编写了initializeView() 的定义,它就会起作用。或者他可以简单地提供view 对象作为initializeView() 中的参数,例如initializeView(view: View?)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-10
  • 2020-04-02
  • 2017-11-22
  • 1970-01-01
相关资源
最近更新 更多