如何在观察实时数据的值时修复“resp”的空指针

Posted

技术标签:

【中文标题】如何在观察实时数据的值时修复“resp”的空指针【英文标题】:How to fix null pointer for "resp" while observing the value of live data 【发布时间】:2019-08-21 02:31:19 【问题描述】:

我的代码在视图模型中运行良好,但是当我开始使用中的实时数据观察值时

model.d.observe(this, Observer<RespCategories> 
                r->resp=r
)

resp=r 中的 r 类型从 RespCategories 更改为 RespCategories? 它与寻呼机适配器的参数不匹配,所以我对其进行了一些更改,例如将var resp: RespCategories 转换为var resp: RespCategories? = null,因此在观察r-&gt;resp=r 的值时出现了一个新问题@ resp 值为空。如何解决问题?

kotlin.KotlinNullPointerException   at com.example.xyz.MainActivity.showData(MainActivity.kt:83)
                      at com.example.xyz.MainActivity$fetchData$1.onResponse(MainActivity.kt:65)

主活动

class MainActivity : AppCompatActivity()
 

    var userService: UserService = ApiUtils.getUserService()
    var dotscount: Int = 0
    lateinit var sliderDotspanel: LinearLayout
    lateinit var sectionPagerAdapter: SectionPagerAdapter
    lateinit var respCategories: RespCategories
    var resp: RespCategories? = null

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

        sliderDotspanel = findViewById(R.id.sliderdots)
        fetchData()


    


    fun fetchData() 

        var call: Call<RespCategories>

        call = userService.getData()

        call.enqueue(object : Callback<RespCategories> 
            override fun onFailure(call: Call<RespCategories>, t: Throwable) 
                Toast.makeText(this@MainActivity, "fail", Toast.LENGTH_LONG).show()
            

            override fun onResponse(call: Call<RespCategories>, response: Response<RespCategories>) 
                Toast.makeText(this@MainActivity, "success", Toast.LENGTH_LONG).show()
                respCategories = response.body()!!
                var dataGenerator:DataGenerator
                dataGenerator=DataGenerator()
                dataGenerator.addData(respCategories)
              //  DataGenerator.addData(respCategories)
                showData()
            

        )

    

    fun showData()

        //var resp:RespCategories=DataGenerator.getData()
        val model=ViewModelProviders.of(this).get(DataGenerator::class.java)
       // var resp=model.getData()

        model.d.observe(this, Observer<RespCategories> 
                r->resp=r
        )

        if (viewPager != null) 

            sectionPagerAdapter = SectionPagerAdapter(supportFragmentManager, resp)
            viewPager.adapter = sectionPagerAdapter

            dotscount = sectionPagerAdapter.getCount()
            var dots: Array<ImageView?>? = null
            dots = arrayOfNulls(dotscount)

            for (i in 0 until dotscount) 
                dots[i] = ImageView(this@MainActivity)
                dots[i]!!.setImageDrawable(ContextCompat.getDrawable(applicationContext, R.drawable.non_active_dots))

                val params = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)
                params.setMargins(8, 0, 8, 0)
                sliderDotspanel.addView(dots[i], params)
            

            dots[0]!!.setImageDrawable(ContextCompat.getDrawable(applicationContext, R.drawable.active_dots))
            viewPager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener 
                override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) 

                

                override fun onPageSelected(position: Int) 
                    for (i in 0 until dotscount) 
                        dots[i]!!.setImageDrawable(ContextCompat.getDrawable(applicationContext, R.drawable.non_active_dots))

                    

                    dots[position]!!.setImageDrawable(ContextCompat.getDrawable(applicationContext, R.drawable.active_dots))

                

                override fun onPageScrollStateChanged(state: Int) 

                
            )
        

    

>Datagenerator
````````````
class DataGenerator constructor(): ViewModel() 

    companion object 
       // lateinit var da:RespCategories
    //   lateinit var da:MutableLiveData<RespCategories>
    

            val d=MutableLiveData<RespCategories>()

    fun addData(respCategories: RespCategories)
       // d=respCategories
        d.value=respCategories

    
    fun getData():MutableLiveData<RespCategories>
        return d
    

>RespCategories
````````````
data class RespCategories constructor(

    @field:SerializedName("type")
    val type: String? = null,

    @field:SerializedName("value")
    val value: List<String?>? = null


)

  [1]: https://i.stack.imgur.com/eDAhx.png

【问题讨论】:

【参考方案1】:

您的代码中有错误:showData() 中的观察者观察一个 DataGenerator 对象,但 onResponse() 回调将数据发布到另一个对象。你应该

关于LiveData 的类型参数可空性的几句话。看Observer界面:

public interface Observer<T> 
    void onChanged(@Nullable T t);

onChanged() 方法的参数用@Nullable 注释。此方法根据LiveData 类型参数的可空性观察可空类型。 即使您的LiveData 使用非空类型参数定义,您也可以期待为空:

如果你在新对象上调用liveData.value,但你可以覆盖默认的空值并设置你自己的

val d = MutableLiveData<RespCategories>().apply  value = RespCategories.DEFAULT 

如果您的 java 代码发布 null 值(不禁止)

【讨论】:

以上是关于如何在观察实时数据的值时修复“resp”的空指针的主要内容,如果未能解决你的问题,请参考以下文章

当需要一个形式参数直接改变对应实参的值时,该形式参数应说明为啥参数?

在检查空值时 onPostExecute 中的 AsyncTask 中的空指针异常

获得额外意图时的空指针

如何修复运行时错误:加载类型为'const char的空指针

Knockout JS,如何在更改可观察数组中的值时更改样式属性

尝试打开 Android XML 文件时如何修复 Eclipse 中出现的空指针异常?