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)
Related
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
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
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.
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.
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 5 years ago.
Improve this question
How can I retrieve the data of a model class from an activity class?
This is the class:
class Mass(
val number: Number,
val date: String,
val day: String,
val reading: Reading
){
}
To access data of Model class i.e. class Mass. You just have to initialise above class in Activity and then you can directly access the variables of Mass Class.
like this :-
val mass : Mass = Mass(12,"08/02/2018","Firday")
textView.text=mass.day