如何延迟为kotlin中的val赋值?

时间:2018-03-20 00:57:17

标签: android kotlin

我将mContext定义为val,我需要在fun onCreate中为其指定一个值。

代码private lateinit val mContext: Context不正确,我该怎么办?

class UIMain : AppCompatActivity() {

    private val mContext: Context

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

        mContext = this
    }
}

回答Strelok

关键字this并不总是合适,就像下面的代码一样,所以我认为将this分配给mContext更为方便。

 private Context mContext;

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.layout_main);

        mContext=this;

        findViewById(R.id.btnClose).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(getApplicationContext(), "Hello A", Toast.LENGTH_LONG).show();
                Toast.makeText(mContext, "Hello B", Toast.LENGTH_LONG).show();
                //Toast.makeText(this, "Hello C", Toast.LENGTH_LONG).show(); //Doesn't work
                finish();
            }
        });
    }

4 个答案:

答案 0 :(得分:4)

如果您使用lateinit关键字,则必须从val更改为var,从而失去不变性。如果这对你没问题,Strelok的答案就足够了。

但如果您因任何原因确实需要代码val,可以试试lazy delagate property

正如Android Essense博客中所述:

  

此属性采用lambda,,这是第一次执行   访问属性。之后,它将返回该值   分配给它。这样我们就可以将属性声明为不可变的,并且   非null,因此只要在我们第一次访问它之前创建了片段(或Activity)。

例如,在您的情况下,您可以尝试这样做:

private val mContext : Context by lazy {
    this
}

简而言之:

  • 如果您的值可以或需要变为可变,请使用lateinit
  • 如果您的价值要初始化一次并在您的方法中共享,请将lazyval一起使用。

但正如其他人所说,在您的具体情况下,最好在需要活动/上下文参考时调用this

修改:根据您的示例,为什么您需要在活动中使用mContext,我仍然说您不需要它。

您可以直接调用this并在匿名函数内的Toast#makeText()上使用它,而不是尝试:

  • this更改为UIMain.this
  • 在Activity中创建一个方法,并在匿名函数中调用该方法。例如:findViewById(R.id.btnClose).setOnClickListener { otherMethod() },在该方法中,您可以再次使用this引用活动。

答案 1 :(得分:3)

我认为你真正想要的是一个合格的表达,如

this@UIMain

,如

Toast.makeText(this@UIMain, "Hello C", Toast.LENGTH_LONG).show(); //works everytime

解决了所有问题。见Kotlin this expression

PS:如果这样可以解决您的问题,您应该将问题重命名为“如何在嵌套对象中使用外部”

答案 2 :(得分:1)

即使是果冻,我们也从未喜欢过吐司。这是一种用自定义可见错误消息替换那片吐司的方法。是的,因为问题是关于吐司的,所以我们包括了吐司。要使用此概念,您需要在屏幕上的某些位置添加TextView。这段代码正在测试两个EditText字段中的有效条目。

    fun onLAMmultiply(view: View ){

    if(etValOne.text.length == 0){
        error("Enter First Value")
        toast("Enter First Value TOAST")
        etValOne.requestFocus()
        return@onLAMmultiply
    }

    if(etValTwo.text.length == 0){
        error("Enter Second Value")
        toast("Enter Second Value TOAST")
        etValTwo.requestFocus()
        return@onLAMmultiply
    }

    var X = etValOne.text.toString()
    var Y = etValTwo.text.toString()
    val multB = {X:Double,Y:Double -> X.times(Y)}
    val df = DecimalFormat("0.00")
    //val df = DecimalFormat("#.##")
    df.roundingMode = RoundingMode.CEILING
    df.format(multB(X.toDouble(),Y.toDouble()))
    etANS.setText(df.format(multB(X.toDouble(),Y.toDouble())).toString())
    etANS.setText(multB(X.toDouble(),Y.toDouble()).toString())

}

fun Context.toast(message: String) {
    Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
}

fun error(msg:String){
    object : CountDownTimer(4000, 1000) {
        override fun onTick(millisUntilFinished: Long) {
            tvError.visibility = View.VISIBLE
            tvError.setText(msg)
        }
        override fun onFinish() {
            tvError.visibility = View.INVISIBLE
            tvError.setText("")
        }
    }.start()
}

答案 3 :(得分:0)

我同意评论的人,为什么你想在私有财产(潜在的内存泄漏)中保留对this的引用,这是很奇怪的。

但是,无论如何,Kotlin有一个lateinit修饰符让你延迟设置属性值,但必须在第一次使用属性之前设置它。

class UIMain : AppCompatActivity() {

    private lateinit var mContext: Context

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

        mContext = this
    }
}