Kotlin: Is this a good way to avoid memory leaks? [closed] - android

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 months ago.
Improve this question
I was always facing this memory leak warning without paying much attention to it, but now I'm looking into how to deal with it and, as I know I shouldn't use WeakReference and that sort of "tricks" to avoid it, come to what I think could be a possible and simple solution.
My idea is as follows:
I have a singleton class (object) which holds all my app configuration, where I initialize a context from the Application class like this:
object AppSettings {
lateinit var context: Context
fun init(appContext: Context){
this.context = appContext
}
/* OTHER STUFF */
}
typealias aw = AppSettings
#HiltAndroidApp
class AWApplication : MultiDexApplication() {
override fun onCreate() {
super.onCreate()
AppSettings.init(this)
}
/* OTHER STUFF */
}
I initialize that context not only in ApplicationClass, but in every activity OnCreate (which inherits from BaseActivity):
#AndroidEntryPoint
open class BaseActivity {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
AppSettings.init(this)
}
}
And finally, I can access context wherever it is needed as follows:
object RandomObject {
fun DoWhatever() {
PlayAFreddieMercurySong(aw.context,)
}
}
Well, this is my possible solution and I would like to know Android gurus from SO opinion about it.
Maybe I'm leaking memory in my App Settings -where I had initially store context-, but Android Studio is not complaining about it, so I am not sure.
In the end, I'm trying to avoid passing context as a method parameter in every place it is needed for code simplicity.

"other stuff" are common between all activities and they need just ApplicationContext, then why you don't use application context in AppSettings. and thats it. BTW your solution will not leak, if and only if you call your AppSettings.init(this) in all activities.
and you don't guarantee that .
in other words "the code doesn't leak now but may be in the future" - vulnerable
if you have functions thats related to activities, fragments or any
class you want, you can use extension functions for that
you should create a kotlin file with name for ex ActivityExt. and write all of your cases that you need for activities . if you need functions for fragments you should also create another kotlin file with name FragmentExt..etc

Related

Why don't we need to pass an argument to onClick() in android [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 12 months ago.
Improve this question
Here's the code
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.myButton.setOnClickListener (object: View.OnClickListener {
override fun onClick(**v: View?**) {
binding.statusText.text = "Button Clicked"
}
})
}
}
Why does this code work when no argument is passed to onClick. I mean 'onClick()' takes a 'View' so we must call it like this: 'onClick(myButton)'.
The user interface control that is clicked, in this case a button, is a View, so it is passed as the argument to onClick().
Because the View.OnClickListener interface explicitly defines that the view that has been clicked is going to be passed to you.
You can certainly omit the value, but it's going to be there. Since it's a compiled language, in order to satisfy the interface you need to take that parameter regardless of whether you'll use it.
In JS world, which you may be getting confused with; is a dynamically typed language and hence in order for things to work you're just required to provide your callback. Either way, the parameters are still going to get passed into the function, but you'll not be referencing/using them
You typically never call onClick yourself. The framework does it for you when you physically touch the view. And it will pass the view you actually touched.
You might wonder:
Why does it even pass it?, I know which view I put the listener on
The thing is. You can give the same listener to multiple views. Having this as parameter makes you able to distinguish in the listener which of the views was clicked.
As a side note, this is a more idiomatic way to write it, and does exactly the same as your code
binding.myButton.setOnClickListener {
binding.statusText.text = "Button Clicked"
}
Writing it like this, will have the view parameter available as it

Is there any downsides to have BaseFragment with an argument? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
👋 I use Jatpack navigation, this is my declaration of BaseFragment:
abstract class BaseFragment<BINDING : ViewDataBinding, VIEW_MODEL : BaseViewModel>(private val layoutId: Int) : Fragment() {...}
so I can have fragments like this:
class DocumentsFragment : BaseFragment<FragmentDocumentsBinding, DocumentsViewModel>(R.layout.fragment_documents) {
My question is, we know we should never have parameters in Fragments to restore states and all, but could Base fragments have them?
Not in this case because there is now a constructor for doing exactly that
https://developer.android.com/reference/androidx/fragment/app/Fragment#Fragment(int)
I would recommend you to analyze it and try to adapt to it, you dont need it in the base fragment.
The parametyzed types thougth seem bad because if you wish to use other type of viewmodel you shoot your self in the foot. By example, does you base view model is a AndroidViewModel? You might need that but cant because you lock your self out. There are other view model types.
It's okay FragmentManager only needs Fragment classes that are added to it to have zero-argument constructor since they're the one that will be reflected.
It's irrelevant if that constructor proceeds to invoke super constructor with arguments.
Even androidx.Fragment has an overload that takes layoutId to inflate instead of overriding onCreateView:
class MyFragment : Fragment(R.layout.my_fragment)

Having context as primary constructor parameter inside a repository is good or bad [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 years ago.
Improve this question
I have a repository called LocationRepository the code of LocationRepository is
class LocationRepository(
private val context: Context
private val api: AppApi,
private val db:AppDatabase
) : SafeApiRequest() {
}
here you can see that I am passing a context inside through the primary constructor need for that is I have to convert a bitmap to base64 from its Uri you can see the suspended fun below
suspend fun submitLocation(location: Location,employee: Employee) : LocationUpdateResponse{
}
you can see here I am passing location which contains the Uri of the image I have to convert the Uri to base64 before API call, is this best practice or bad?
It's neither a best practice nor bad. Having context there is necessary some times especially when you need it for accessing your database, your shared preferences or getting some resources.
If you need the context to live in your repository, you need to be sure you are using the application context. If you are using an activity's context, then you would leak your activities when the activities go away but the repository is not.
Both Activity and Application context are very similar as to what they are providing. The difference is that Activity context is tied to the activity's lifecycle where the application context is tied to the application lifecycle.
Now, since the application will live as long as your repository then it's fine to use application context in your repository.

Kotlin instance variables in Android: assign random value vs dealing with nullability [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 years ago.
Improve this question
Imagine two (equivalent) scenarios in Anroid development with an instance variable:
private var myAmazingVariable: Int? = null
override fun onCreate(savedInstanceState: Bundle?) {
myAmazingVariable = incomingIntent.getInt("INT_PLACEHOLDER", 0);
}
This scenario sets the initial value as null, meaning we have to deal with nullability.
private var myAmazingVariable = 0
override fun onCreate(savedInstanceState: Bundle?) {
myAmazingVariable = incomingIntent.getInt("INT_PLACEHOLDER", 0);
}
In contrast to the above, this scenario initially sets the variable as 0, meaning we don't have to deal with nullability BUT probably require some initial resoureces at initiation.
My question is which of these is a better approach. Both lateinit or not defining a variable are unfortunately not options.
I would say that both options are valid and expected, even the lateinit which as you mentioned is not an option.
It's important on what you would like to do with the variable.
Do you want to treat the variable as nullable to detect if the intent's extra was read? If yes, then go with nullable.
Do you want to treat it as non nullable and have a single default value for when the argument is missing? If yes, then go with the second option.
In my opinion, this kind of options should be consistent across a code base, therefore the better approach is to pick one which will be followed across the whole project so you know and recognise the case immediately without having second thoughts on what that might be. At the end of the day, it doesn't matter which one you choose.
Have you considered lazy?
private val myAmazingVariable by lazy { intent.getIntExtra("INT_PLACEHOLDER", 0) }
In your example of passing in an Int this is a great solution as you can provide a default value. You do need to be careful with other types though as they can be nullable. It's an option if you can be certain that the Intent contains this extra though.

Why does Android require a Context to access a resource? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
I get why Android requires you to pass a Context object when trying to get a view for example, show a Toast, etc.
However, I don't really get the point for requiring it to access resources that could be shared by different Contexts in your application.
I several times found myself trying to access a resource from a utility class using a static method or something along those lines, and find it pretty annoying to require a passing of a Context param.
I fail to see where something could go south with this.
From the official documentation :
Interface to global information about an application environment. This
is an abstract class whose implementation is provided by the Android
system. It allows access to application-specific resources and
classes, as well as up-calls for application-level operations such as
launching activities, broadcasting and receiving intents, etc.
In clear, the context is the middleman between the telephone resource, and your code. And it seems logical, that you cannot access to this from everywhere.
The reason you can only access to Context in Activity and Application classes, is because both derives from Context :
java.lang.Object
↳ android.content.Context
↳ android.content.ContextWrapper
↳ android.view.ContextThemeWrapper
↳ android.app.Activity
Extend Application class by your own public class MyApp extends Application and register MyApp in your manifest and have MyApp something like this:
class MyApp extends Application {
...
private static ApplicationContext context;
#Override
public static void onCreate() {
super.onCreate();
context = this;
}
public static String string(int resId) {
return context.getString(resId);
}
}
Then you can do MyApp.string(R.id.mystring) from everywhere. You can do the same for other resource types.
You can also do (MyApp)getApplication() if you prefer so.

Categories

Resources