Move Sensor data to a different class/activity - android

I have a simple app, it logs a bunch of sensor/gps data. The first activity is a mess, and way too long, so i wanted to modularize it. I want to have 3 modules now:
Main Activity
Sensor Data (Gyroscope, accelerometer, etc)
GPS Data (Position, elevation, etc)
What is the best way for me to go about modularizing this? I was trying to move some of the Sensor Data out of the original class, and then I noticed that my class needed to extend some android.content.context (such as an Activity) in order to access the sensor data properly?
Thanks for a nudge in the right direction.

From my comments on the original question...
You don't need to extend Context - you can create helper classes and simply pass the Activity Context into the class constructor or into the various methods using this from the Activity.
As long as you design your helper classes correctly then it is fine and it is something that many people do and, indeed, there are various Android classes which require a Context parameter. Avoid memory leaks and use the right Context.
Sometimes using the application Context might be better as it is persistent for the life-time of all application components. It is, however, only a partial context in that certain things won't work with it (some UI-related tasks, for example). Otherwise using the Activity Context is fine as long as nothing holds a permanent reference to it (which can cause memory leaks if the Activity is destroyed.

Related

I don't know how to get the screen density for use in a class

I'm teaching myself how to program in Kotlin and I've run into a problem when I've tried to make a function in a class to handle some math for me.
The problem I've run into is that I don't know how to get the screen density as a var/val in the class that is out side of the MainActivity.kt
I've searched a lot for the answer and I can't seem to come up with the right term to get the resources that I need and it's driving me crazy. Every answer I've found either doesn't work or Android Studio says it's going to cause a memory leak.
I know how to get the density in the MainActivity.kt by using this code.
val scale: Float = resources.displayMetrics.density
Thanks for any help. I'm really enjoying learning Kotlin and how to make apps.
You need to access resources through a Context, as in context.resources.displayMetrics.density. An Activity is a Context, which is why you can just access resources directly (technically it's this.resources, where this is the Activity)
If you're calling that directly within an Activity, it shouldn't be a problem! If it's in another class, you'll have to get a Context from somewhere - ideally passing one in (e.g. if an Activity is calling a function, it can pass itself as a Context parameter).
There are a few things that are Contexts, but in this case specifically, you need to be careful:
After Build.VERSION_CODES#R, Resources must be obtained by Activity or Context created with Context.createWindowContext(int, Bundle). Application#getResources() may report wrong values in multi-window or on secondary displays.
Basically the Context needs to have an idea of how big the app window is, which an Activity will, but something like applicationContext might not.
The main reason to be careful is that Activities are big, so you don't want to hold onto them when they're being passed as a Context, because you might keep them in memory after the Activity has been discarded - that would be a memory leak, and it might be what you're getting warned about!
Typically if you did need to hold onto the Context for future use, you'd do something like myContext = passedContext.applicationContext - so you're not holding on to whatever object was passed in, you're plucking out the shared application context which is always in memory anyway, so it doesn't matter if you keep it. That's a safe way to store one.
But like the docs mentioned above, that's no good here, so ideally your function would:
use the Activity context to calculate whatever within the function, and use/store that value, discarding the context, or
access something within the context (resources, displayMetrics etc) and store that if you need to access it later
that way you're storing what you need to, and not holding onto the Activity when you don't need it
Contexts are weird when you're starting out, but they're basically something that provides access to information about the environment the code is running in, and system functions. And some are more specific - like an Activity is a visible component in your app, so it can provide info like the dimensions of its window, things like that.
So they're really important for Android apps, and you end up passing them around a lot (you'll see them as parameters in a lot of functions), but you also have to be careful of keeping Activitys in memory by storing references to them in components that outlive the Activity itself. Hope that makes some sense!

How do I learn which Context I have to use for each situation in Android?

I'm learning Kotlin and I've already had to fill the context several times in different ways, like this, context.application, requireContext() etc.
I'm wondering if there is any way I can realize which context to use by myself instead copying them with tutorials.
There are mainly two type of context in android & both of them are provided to you as a ContextWrapper class object.
Application Context
This context is basically provided/used when you need to do some work that doesn't involves any view/UI operation (where you don't need to refer to/rely on any UI code).
This is mostly helpful when you're doing operations directly via your process that doesn't need any UI interactions like for an example, getting list of contacts via content provider.
So, you can consider this as parent of all other context you can have in your application and apparently this is consistent for your given process.
This context is retrieved via Application class of your app, or via any other activity by requesting like (activity.applicationContext).
Activity Context
This context is basically bounded/limited to given activity you're in right now. This is helpful to mainly do UI operations because, your context is part of the same UI you are in right now.
So, yes you can consider this a child context that can changes as per your activity changes. For most of the cases, it is not preferred to store & share this context across UI/Activities as it can lead to memory leaks.
This context can be retrieved once you're on any activity class via (Activity.this, this, context in fragments & custom views)
I agree personally that context has been confusing topic on Android since the beginning, but if you know C/C++ then I can relate this to 'pointers' (conceptually). Context are pointers for given activity/application class.

What are the downsides of having a static Context variable in an Android application?

In Android programming the single most used parameter that is passed almost everywhere is Context. And we know the purposes it serves. But we can't find out why we should pass it for those purposes, and why not accessing it from a global static place.
Based on Uncle Bob's Clean Code, one way of getting cleaner code is by reducing parameters, making them more meaningful to the task you're doing. Based on this, and based on DRYing parameters, we decided to give it a shot, and create a fully-featured application that has activities, fragments, foreground and background services, notifications, media, etc. and uses many device APIs like camera, GPS, etc. and is a real-world application, and only have one static context initialized at the application creation.
So in the application creation we created a public static Context context variable, and we initialized it using getApplicationContext() method in onCreate() override.
Then instead of passing context like this, getContext, etc. throughout code, we simply used App.context, and we didn't pass it as a constructor parameter to our adapters and other utility functions.
Now after venturing this bold movement, we don't see any problem with our app. Everything works just fine, battery consumption is not changed, at least it's not measureable to us so it's very low. Memory consumption is not changed and we can't measure it. Application performance and speed is not changed measurably.
So we have this really big question in our mind that, what are the downsides on our approach? Why Android guys don't just expose a global context that can be initialized and remove all context parameters from the entire ecosystem, only accessing that global variable anytime they need it?
Please read this blog carefully you will understand Context better.
Static variables defined at global scope of the class and so they also refereed as class member.
You can not control creation and destruction of static variable.
Usefully they have been created at program loading and destroyed
when program unload.
Since static variable are class member, all threads tries to access
them has to be manage.
If one thread change value of a static variable that can possibly
break functionality of other threads.
In my projects, I use the static application context for everything except graphics. The fact is that the application context does not contain information about the style and if you create a widget based on it, then it will have a default style.
On this moment, I have never faced the problems of this approach. Importantly, I do not write tests for my projects. But I'm sure that this will not be a problem.
I also will be very grateful if you point me to the problems of such use of the context. (except testing)
Your application doesn't break because you are using the Application Context: this may not be THE best practice, but it is generally fine.
What you are missing there is that Context is an abstract class with many different implementations (an Activity is a Context, a Service is a Context, the Application is a Context) with different properties and capabilities. The Activity has an entire graphic context associated whit it and a full view hierarchy that can occupy megabytes in memory.
One common mistake (that I did myself in my early days) was to store the Activity in a static field: this led to memory leaks by having two entire views hierarchy in memory as soon as the user puts the app in background, the Activity reaches onDestroy(...) callback and the user opens the app again.

How many types of context in android and what is better to use

I just wanted to know how many ways to get the context, which method used in which situation.
Which one better to use, and what is the main and key deference between them.
For Your better understands you should read android official blog. an also look at HackBod Answer.
There are some references URL which help you more about the context
What exactly does using the Application Context mean?
Difference between Activity Context and Application Context
http://android-developers.blogspot.de/2009/01/avoiding-memory-leaks.html
Thanks
Context class represents the local environment of an App, It encapsulates all the services and resources available to the app. There is a base class ApplicationContext, and sub classes for components: Activity, Service etc.
Always prefer using ApplicationContext because it is global and doesn't cause serious issues if its leaked, that is: an unused reference of it stays and is not garbage collected.
Sometimes you have to use sub components like Activity or Service as context. Use this when creating Intents, or creating UI Elements, or showing a toast etc. That is: functions that are specifically bound to these component's identity, its UI or its display window.

Static methods vs. class extending android.app.Application?

I have a class which extends Application in an Android tabHost app. In the App class, I've been placing methods and variables which I would otherwise need to re-create in every class. One method reads from a DB and stores results in an ArrayList (first name, last name for instance). Rather than re-reading this database and re-creating the code for every tab view which needs the info, I've stuck the method and ArrayList in a class extending Application (myAppClass). This way, by setting up mAC = (myAppClass) getApplicationContext() from any tab view in onCreate() I can reference all the get..() and set..() methods in myAppClass.
My original plan was to use a shared class with static methods and variables but I read a lot of "don't do that" threads so decided to go the Application route. Now, I've run into a situation where I'm trying to use myAppClass in a Project Library but getting errors about android.app.Application cannot be cast to... If I change myAppClass back to static methods/variables (and do not extend Application) things work, but this is supposed to be a big no-no. Is there another way to do this? Not sure if Android passes everything by reference but Would I be better off to re-implement the entire application by passing huge (thousands of objects/members) ArrayLists back-and-forth between methods/classes?
My original plan was to use a shared class with static methods and variables but I read a lot of "don't do that" threads so decided to go the Application route.
The "don't do that" is generally a recommendation against anything in global scope and therefore would cover static data members as well as a custom Application. Both are likely sources of memory leaks.
Now, I've run into a situation where I'm trying to use myAppClass in a Project Library but getting errors about android.app.Application cannot be cast to...
Your manifest in the hosting project probably does not state to use the library's Application implementation.
this is supposed to be a big no-no
Again, static data members are no worse than a custom Application, and in many cases are better.
Is there another way to do this?
Don't use either an Application or static data members.
Would I be better off to re-implement the entire application by passing huge (thousands of objects/members) ArrayLists back-and-forth between methods/classes?
You would be better off having a persistent data model, such as a database. Using static data members as a cache for a persistent data model is OK, so long as you are very careful about your memory management.

Categories

Resources