I want to run a job using JobScheduler, and within that job I need to execute a method on a class which is an implementation of a specific interface, so it isn't a POJO or something like that which can easily be passed as a JSON string.
What I currently thought was to serialize that class to a file and then retrieve it later from within the JobService.
Is there any better way to do it?
Thank you.
You could use the build-in method setClipData(ClipData, int) - link, where you could apply deserialization of that object in the moment, when the Job will be triggered.
Related
Currently, I have a database manager class that handles all operations to the database like this:
class DatabaseManager(val context: Context) {
private val db = Firebase.firestore
//Other functions, etc.
}
It makes use of the context passed in by different activities to perform functions to the database. The thing is, every single activity that requires database functions have to instantiate this manager class first, then call the functions. I would like to make use of the Singelton design pattern to make it such that all the activities will only use a single instance of the class. I believe kotlin's objects can do this, however I also need to be able to pass in the context of the activities into this manager class. Any assistance is appreciated, thank you!
I would recommend not doing that. The problem with Singletons is that they make code hard to test, you can't fake out the database. And for a database this is a particularly bad problem, as setting up all the right fake data can be painful. Instead, take a look at injection. It can do the same thing (make a single instance shared between everyone who needs it), but it manages that global state rather than having the classes themselves manage it via a static reference, passing it in (generally via the constructor) to whoever needs it. This makes it easy to provide an alternative or mock database when needed for testing. Injection used to be a bit painful to set up, but Hilt makes it a lot easier these days.
I can make calls without a hitch as long as there are no parameters. I know that as a beginner to app programming that this will be a ridiculously simple thing I missed or something overly complex, but here goes.
I have an interface inside a fragment and have the #Query in place like so:
interface RewardsApiService {
#GET("JSON/return-data.asp")
fun getCID(
#Query("cid") strCustomerID: String,
#Query("process") strProcess: String
)
fun getRewards(): retrofit2.Call<ResponseData<List<RewardsCards>>>
}
My question is this: Where do I define and assign those variables, strCustomerID and strProcess, so the interface can use them? strCustomerID is a SharedPreference.
The short answer is: You don't. Retrofit autogenerates the code based on what you have tagged with #GET, #Query, etc.
You should call it like this:
val call = service.getCID("foo", "bar")
However the generated call will url will look like this:
[your base url]/JSON/return-data.asp?cid=foo?process=bar
So make sure that url matches what you want.
Outside of the retrofit specific stuff there are some deeper architectural concerns. I'd have a look at https://developer.android.com/jetpack/guide and consider restructuring the project slightly.
For example, you dont want to be making API calls from within a fragment. This creates concerns around potentially doing IO on the main or UI thread and you are likely to end up trying to figure out crashes around that.
At a bare minimum I'd recommend splitting the interface out into a separate file and making sure your network call is done within a coroutine with IO scope.
So I have a Game object that has an init block where I setup the object and upload to the Firebase Firestore. Then when I'm listening for changes in that object I have to convert the DocumentSnapshot to a Game object.
game = snapshot.toObject(Game::class.java)
Pretty simple. The problem is is that this calls the init block of my Game class and uploads another game object. Is there a way I can avoid calling the init block while doing this? Thanks!
When you use automatic field mapping like this, the convention is that you should use a class definition that contains only the fields you want to map, and nothing else. Objects that have only getters and setters for properties are called JavaBeans, and their sole purpose is to store data. These objects must define a default no-arg constructor.
If you have additional logic that works with your Game object, that should go in a different class. It's better design to keep your data separate from the logic that works with the data (as you have discovered).
Move your init code to a constructor, which you can call when you're creating an instance of your Game class and you want it to upload the game object.
In my app I have a-lot of Web API calls which returns me JSON. I am trying to do this thing simple. I don't want to create AsyncTask in every fragment. I have tried many things but nothing give me the solution how to do this. I need one Class solution in which I call a method with a url argument and get result in calling fragment or activity. Can someone share best practice to do this?
I have tried otto library but It seems it don't fulfill my requirements.
Web communication should not be done in main thread, therefore, some kind of threading is necessary. I think AsyncTask is the easiest way. I suggest creating abstract class, implementing network-stuff, and leave parsing output for child classes. Something like this:
abstract class DownloadJSON extends AsyncTask<...>{
DownloadJSON(List<NameValuePair> httpParams){...}
JSONObject doInBackground(String... urls){... return mJSONObject}
abstract void onPostExecute(JSONObject json);
}
You may override doInBackground for further background parsing or just display contents in onPostExecute.
Please check the library called Retrofit. It turns your REST API into a Java interface and has asynchronous execution of requests. It even converts your JSON response into Java objects.
I am getting into Inversion of Control, specifically using Guice and RoboGuice for Android and I have a question.
I have a method call that returns a Resource (which is essentially an XML or JSON String).
public Resource getResource(){
// Some implementation details that call a web service and throw the result in a string...
String resource = ........
}
The Resource class is really just a wrapped String, so I figured it made sense to pass it in in the constructor, since it is an essential part of a Resource object.
public class Resource{
Resource(String theXMLorJSON){
...
}
}
A couple of questions:
How do I construct a new Resource in the getResource call? I would think that I want to use IoC and not call new in the method.
If another class takes a Resource in the constructor, how can I use the Guice container to construct it when I need a dynamic String at construction time? I just asked a similar question and believe there may be a specific way to handle this using Guice.
Thanks so much!
I think you may be misunderstanding something about dependency injection. You don't need to try to avoid using new in all cases... you primarily want to avoid using new to create anything that you might want to be able to mock out for testing, and it's generally best to allow the container to wire up any class that depends on such an object.
Your Resource class, though, sounds like a simple value object that you can easily create manually in any testing you do. It also doesn't depend on any kind of services... it just contains a String. So there's no reason to try to have the container create it.
The class containing the getResource() method, on the other hand, you definitely want the container to create, because you'd like to be able to use something that depends on that class in testing without having to actually call a web service.
Note that if you have a class with a constructor that takes both dependencies you want injected by the container and parameters that are only known at runtime, you need to create an intermediate factory of some kind with a method that only takes the runtime parameters. With Guice you can automatically create such a factory from an interface using the Assisted Inject (not sure if that works with RoboGuice, but it's easy to create such a factory implementation manually too).