java.lang.OutOfMemoryError in class instance using Kotlin - android

I making project in Kotlin with MVP design pattern first time. Why I have got java.lang.OutOfMemoryError.
This is my error from debuger: https://pastebin.com/U1nwjaf6
This is my class DbManager: https://pastebin.com/KRpa2eRF
And this is my class LoginPresenter: https://pastebin.com/Vryf0kBH
I am beginner on making apps using Kotlin.
Please help me.

Welcome to StackOverflow!
Some tips:
You should post everything related to your code. It makes easier for people to help you and give better answers. You should also paste code in the question itself instead of giving links to pastebin. Only use pastebin like services when your code is too big. Which is not the case here (but you did right with the error message, it is big).
Now, to the problem itself.
You seem to be instantianting the class DbManager, according to the error messages. This class instantiates your other class, LoginPresenter here:
class DbManager
{
...
val loginPresenter: LoginPresenter = LoginPresenter()
...
}
LoginPresenter will instantiate the class DbManager:
class LoginPresenter
{
...
val dbManager: DbManager = DbManager()
...
}
DbManager creates LoginPresenter which creates DbManager which creates LoginPresenter which creates...
See the pattern here? It creates a infinite loop, with recursion, that will create classes until you run out of memory. Hence, the error.
It is hard to tell you what you should do when I only have this part of the code. But, I think that you should instantiate the DbManager class only once, globally and use that instance everytime you want to interact with it.

You are getting this because of StackOverflow :)
DBManager & LoginPresenter instances are getting created in a loop and causing this, you should move instance creation into some method

Related

Room-based code is causing the following error: android.app.Application cannot be cast to com.example.mathreps.MathRepsApplication

I am working on adding data persistence to an app using the Room library, based on this documentation. My database only has one column where a String corresponding to a user-selected radio button is to be placed. However, as soon as I attempt to insert a new object (in this case, an Attempt), it gives me the following error:
java.lang.ClassCastException: android.app.Application cannot be cast to com.example.mathreps.MathRepsApplication.
I believe this error comes from the following block of code within my Rating fragment:
private val dataViewModel: MathRepsViewModel by activityViewModels {
MathRepsViewModel.MathRepsViewModelFactory(
(activity?.application as MathRepsApplication).database
.attemptDao()
)
}
Which relates to a different class called MathRepsApplication
class MathRepsApplication: Application() {
val database: AttemptRoomDatabase by lazy {AttemptRoomDatabase.getDatabase(this)}
}
Since this problem most likely relates to multiple classes and packages, here is the link to the repository for the project.
My attempts to fix this have been unsuccessful, with them mostly consisting of heavily reviewing the database implementation and not much else, as I don't exactly know where to start.

Will making application class singleton cause memory leak?

I created a custom Application class for my app. This class onCreate sets a static variable of itself like this
public void onCreate() {
super.onCreate();
mInstance = this;
}
public static ChattyApp getInstance() {
return mInstance;
}
Then I use App.getInstance() method to get application context to a nonactivity/fragment class like API Controller or something. Can it cause a memory leak?
I setup leak canary and it is showing memory leak on an instance variable of Application class. This variable keeps socket.io's socket ref so that I can use it anywhere in the app.
It is a good question that you have asked and people on SO have had extensive discussions on this. Have a look at this and this
Although this seems to be an okay way to store the Context in Application class as per the discussion in the first link, there can be better ways to deal with this.
Ideally for each logic unit you should have a separate class to deal with it rather than polluting your application class. You application class can however initialize or setup those other classes. This will create a separation of concern.
Another way is to use Dagger2, which is a dependency injection framework, to inject your socket ref to wherever you want.
Dagger 2 has a steep learning curve and but a very important tool to learn as an Android developer

Drawable in ViewModel with MVVM concept

I confused with MVVM concept that ViewModel should not reference View.
In my usecase , I have to use Databinding and wrapping the Drawable by LiveData and observe its value in xml view.
Base on suggestion from Android I implemented as below
https://developer.android.com/topic/libraries/architecture/viewmodel
If the ViewModel needs the Application context, for example to find a
system service, it can extend the AndroidViewModel class and have a
constructor that receives the Application in the constructor, since
Application class extends Context.
MyViewModel.kt
class MyViewModel(application: Application): AndroidViewModel(application){
private val _showIcon = MutableLiveData<Drawable>
val showIcon: LiveData<Drawable>
get() = _showIcon
fun applyChanged(){
if(condition){
_showIcon.value = AppCompatResources.getDrawable(getApplication(),R.drawable.icon1)
}else{
_showIcon.value = null
}
}
}
main_activity.xml
android:drawableTop="#{viewModel.showIcon}"
Question:
This approach is OK with MVVM concept ? Is there anything I have to do with context inside ViewModel to prevent leak memory problem?
Or any potential problem in my code ?
Thank you so much !
I don't see any need to use databinding or view models for what you want to do. Just refer the drawable directly in xml file. If it is null, it won't be there. This is valid because you are getting the image resource from your own resources. If you were supposed to get any drawable from server or local database your approach would make sense.

Kotlin do not call super

I have a class that extends another, but in this class I do not want to call the super constructor.
How can I solve it?
Here is a snipet of my code
class SubarticlePagerAdapter(fragmentManager: FragmentManager, context: Context, var selectedArticleName: String) : ArticlePagerAdapter(fragmentManager, context) {
var subarticleDao: ArticleDao
var itemCount = 0
init {
ApplicationHelper().getApplication(context).appComponent.inject(this)
subarticleDao = ApplicationHelper().getApplication(context).subarticleDaoSession.articleDao
initBundles(context)
}
override fun initBundles(context: Context?) {
}
}
My problem, when this constructor is called, parent class constructor run first, and initBundles() will be called from there, but at that time subarticleDao and selectedArticleName are not set and I get exception.
TL;DR
I'd advise you to move the code from the init block to the initBundles function and use your variables there after initialization. Then there would be no need to avoid calling the superclasses constructor.
Extensive Answer
I think you should think about what you want to do with your design. Working around the idioms of a language is not very often a good idea or a sign of good design - at least when kotlin is your language :)
What you did with your code (overriding a - possibly abstract - method, initBundles from your superclass is pretty much the template method pattern. So it seems to me the purpose of initBundles is to let subclasses customize parts of the initialization... What basically is what you do in your init block.
EDIT: As Paul pointed out in the comments, you can't use the member selectedArticleName before your base classes initialization has finished. So if the base class calls initBundles during its initialization, then properties in the subclass won't be initialized as also stated at Paul's link.
Since in the snippet you don't use selectedArticleName, you could just move your initialization stuff to the initBundles function and init your subarticleDao there.
However, if you need to use your subclasses properties at that point, I'd really advise you to rethink your design. There should be several ways to solve this, but to decide what would suits your requirements best one would need further insight into the intentions you have with your design.

Cannot reference class from another class in same package

I'm admittedly new to Scala and Android programming and in all my searching I haven't been able to find answer to help me understand and resolve my problem.
Here's a gist of my two scala classes https://gist.github.com/Daikamar/f15288a7bf732cd5b55c
I'm running through the tutorial found here: http://developer.android.com/training/basics/firstapp/starting-activity.html
which I'm trying to adapt to scala code (I have need for understanding Scala for work and a personal desire to mess around with Android development so I figured I'd try and combine these efforts).
The problem is seen in DisplayMessageActivity.scala in which the IDE reports that it cannot resolve MyActivity in this line:
val message = intent.getStringExtra(MyActivity.ExtraMessage)
I feel like this should work. I can get it to resolve if I change MyActivity to an object, but then that breaks other pieces of the application that expects MyActivity to be a class.
An help in getting me to understand my problem would be appreciated.
You cannot reference the ExtraMessage field from MyActivity as though it was a 'static' field (in Java terminology). To access ExtraMessage in your other activity you will need to either obtain an instance of MyActivity that you can then de-reference, or add a companion object (defined using the object keyword in the same file in which the class is defined) for MyActivity and define the field there:
object MyActivity {
val ExtraMessage = "net.daikamar.myfirstapp.MESSAGE"
// any other 'static' declarations
}
class MyActivity() extends ...
then your call as above will work.

Categories

Resources