2

I was trying something and stumbled upon a problem where I can't access a global variable str1 from a class MyAsyncTask. I'm guessing, its got to be some declaration error but I'm not too sure as to as to what is being violated.

class MainActivity : AppCompatActivity() {
    var str1 = "0"

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

        for (i in 0..5){
            val myAsyncTask = MyAsyncTask(this@MainActivity)
            myAsyncTask.execute("-")
            str1 = str1 + "1"
        }

    }
    class MyAsyncTask(private var c : Context):AsyncTask<String,Void,String>(){

        override fun doInBackground(vararg str: String?): String {
            str1 = str1 + str[0] + "2" // str1 is bolded in red, somehow, i cant access it
            return str1
        }

        override fun onPostExecute(result: String?) {
            super.onPostExecute(result)
            Toast.makeText(c, result, Toast.LENGTH_SHORT).show()
        }
    }
}
Zoe
  • 27,060
  • 21
  • 118
  • 148
Rajdeep
  • 2,246
  • 6
  • 24
  • 51

2 Answers2

7

As a general rule, if you have something in Kotlin that, with a similar syntax, would work in Java, decompile the Kotlin code. In IntelliJ/Android Studio, Tools -> Kotlin -> Show Kotlin bytecode. With a slight edit so the code compiles, you'll see the declaration for the class is public static final class MyAsyncTask extends AsyncTask. If you're familiar with how inner classes work, you'll know that static inner classes are like declaring them in a separate file; they do not have context related to their outer class, and can therefore not access non-static variables. It's kinda like accessing a non-static variable from a companion object or a static method. Static anything isn't attached to a specific instance of an object, and can therefore not access non-static variables.

That is the problem. If you google what you want from here, you can usually find links to documentation, at least for basic language-related stuff.

Kotlin has a special keyword you have to use if you want regular inner classes. The keyword is pretty straight-forward too: it's inner. Change your class declaration to inner class MyAsyncTask, decompile, and see how it changed to public final class MyAsyncTask extends AsyncTask.

TL;DR:

This in Java:

public class MyClass {
    public class Something {}
}

Is this in Kotlin:

class MyClass {
    inner class Something 
}
Zoe
  • 27,060
  • 21
  • 118
  • 148
2

To access the member of outer class you must have to use inner class in kotlin unlike JAVA.

here is the referecne https://kotlinlang.org/docs/reference/nested-classes.html#inner-classes

So your code should be like ...

class MainActivity : AppCompatActivity() {
    var str1 = "0"

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

    inner class MyAsyncTask(private var c : Context):AsyncTask<String,Void,String>(){

        override fun doInBackground(vararg str: String?): String {
            str1 = str1 + str[0] + "2" // str1 is bolded in red, somehow, i cant access it
            return str1
        }

        override fun onPostExecute(result: String?) {
            super.onPostExecute(result)
            Toast.makeText(c, result, Toast.LENGTH_SHORT).show()
        }
    }
}
Moinkhan
  • 12,732
  • 5
  • 48
  • 65