I'm using TTS in my app. I want to run a method when I ask for it. I created a Hashtable where I want to store my methods like:
table.put("qqq", say("www"));
I'm comparing my data with keys - it works, but it does not trigger a method.
This probably isn't possible with Hashtable, so please tell me how to do what I want in the simplest way
You should save the Object which calls that method:
Hashtable<String, MyObject> objects = new Hashtable<String, MyObject>();
objects.put("qqq",new MyObject());
MyObject test = objects.get("qqq");
test.say("www");
Check out java.lang.reflect, might be the right thing to use in your situation.
With reflection you can do something like this:
Method method = myObject.getClass().getMethod("say", String.class);
method.invoke(myObject, "www");
So all you would need to do is store the object, method name, and parameters and then you can dynamically invoke the method.
probably it is more a design issue.
Solution could be: if You are using only say() method, then store just a parameter that You would pass to the say() method (E.g., table.put("qqq", "www");). And when You need particular phrase to be found just call say(table.get("qqq"));.
Related
When i am using WorkManager and I'm trying to pass some object to it
Data data = new Data.Builder().put("passstring",object).build();
getting me Builder.put can only be called from within the same library group (groupId=androidx.work) error
You can use workDataOf() method. Just make sure you pass Pairs of data
eg.
workDataOf(Pair("param_name", "data"))
Looks like you should use putString method like this.
Data data = new Data.Builder().putString("passstring",object).build();
Because put method marked with annotation #RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) and not documented here:
https://developer.android.com/reference/androidx/work/Data.Builder
Currently, I still wondering when we implement Parcelable interface for a class, how can we decide when to use writeTypedList/ readTypedList or writeList/ readList
Read
// Using writeTypedList
parcel.writeTypedList(watchlistColumnTypes);
// Using writeList
parcel.writeList(watchlistColumnTypes);
Write
// Using readTypedList
watchlistColumnTypes = new ArrayList<>();
in.readTypedList(watchlistColumnTypes, WatchlistArrayRecyclerViewAdapter.ColumnType.CREATOR);
// Using readList
watchlistColumnTypes = new ArrayList<>();
in.readList(watchlistColumnTypes, WatchlistArrayRecyclerViewAdapter.class.getClassLoader());
Both workable for me. But, I'm not sure what is the difference between both, and how can we choose among them?
I think the rule of thumb is that, we should use writeTypedList or readTypedList whenever we could, and use writeList or readList whenever you need to.
This is because writeTypedList or readTypedList seems to have better performance.
According to https://android.googlesource.com/platform/frameworks/base/+/1a008c1/core/java/android/os/Parcel.java#117
There are also some methods that provide a more efficient way to work
with Parcelables: writeTypedObject(T, int), writeTypedArray(T[], int),
writeTypedList(List), readTypedObject(Parcelable.Creator),
createTypedArray(Parcelable.Creator) and
createTypedArrayList(Parcelable.Creator). These methods do not write
the class information of the original object: instead, the caller of
the read function must know what type to expect and pass in the
appropriate Parcelable.Creator instead to properly construct the new
object and read its data.
I have created one activity that creates user profile and stores its information like name,id, profile pic etc.
This information is unique and should be use in all activities in application.
I want to know which is best way to create a common object that stores all information and use it in all activities.
I have read about bundle and JSON but can't understand it how to use it.
Please help me as to what option should I choose. I have done a lot of reading but not sure as of now. Please help me with whats the standard thing to do and what would be better.
You can use Application class for accessing same object across many activities.
public class TestApplication extends Application {
//Object declaration
public TestApplication () {
// TODO Auto-generated constructor stub
}
#Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
}
//setter getter for object
}
Now in your Activity:
//after setContentView
TestApplication testAppObj = (TestApplication) getApplication();
testAppObj.setSomeObj(myObj);
//retrieve as:
someObj = testAppObj.getterMethodOfObj();
You must register your Application class in your manifest file just like you register your activities:
<application
android:name="com.pkg.test.TestApplication " />
Hope this helps.
You can create your custom Application (like others said) and then you will have a global access to this information but I think this is not a good design because your activities will be tied to this Application implementation (you will not be able to use this activities in a different App).
I suggest you to implement a Service and use this Service in all the activities.
Check the next article to create a background service which will be active for all the activities:
https://developer.android.com/training/run-background-service/create-service.html
Best way to implement this is to save data in Prefrences and retrieve whenever required. To simplify this you can directly store an Object in prefrences and get that object whenever required.
To save object you will require GSON library to be added in your libs folder and the you can conver any object to string and store anywhere you want like this.
Object-->>String >>>
Gson gson = new Gson(); String json
=gson.toJson(Object);
Getting object back
String -->> Object >>> Gson gson = new Gson(); Object obj
=gson.fromJson(json string);
The above method will return in a persistent storage and you won't keep memory occupied all the time.
Static variables can be freed by system on memory requirement, hence not recommended.
The Application way is the best, but if you want to check here is the official list of common ways to do that.
is there Any Way To Make my Method Take many input variable but with out overloading ... could be my question not clear ... I mean Like That :
if I Have This Method
public void setValues (int val1,int val2 ,String val3){
}
what I want is : use this method with many way
setValues (val1,val2)
OR
setValues (val3)
why I want to do that with out overloading : Because if i have as example 10 variable i want to add many method with overloading but i don't like that ...
is there any way helps me to check variable or skip it in the same method ..
Thanks for help .
You can use varargs future to partially solve your problem http://docs.oracle.com/javase/1.5.0/docs/guide/language/varargs.html
This can be done if you have parameters of a same type.
But it will require that you will pass variables with the same type as a last param. It is not completely what you want, but it is a small workaround.
No there's no way to do that in Java without method overloading. One alternative would be to group those parameters which are related and make them fields of a class. Then the method would take an instance of that class as a parameter, and which ever parameters were optional would then be null.
I am trying to create helper method that would iterate through all Bundle objects, in a generic manner.
By "generic" I mean:
Doesn't need to know the names (keys) of the objects in the Bundle passed as a parameter.
Doesn't need to change if another member (key) was added to the Bundle in the future.
So far, I figure out the following outline to accomplish that:
private void bundleToSharedPreferences(Bundle bundle) {
Set<String> keys = bundle.keySet();
for (String key : keys) {
Object o = bundle.get(key);
if (o.getClass().getName().contentEquals("int")) {
// save ints
}
else if (o.getClass().getName().contentEquals("boolean")) {
// save booleans
}
else if (o.getClass().getName().contentEquals("String")) {
// save Strings
}
else {
// etc.
}
}
}
Does this approach make sense at all?
Is there a better way of accomplishing this?
Could you save everything as String using the toString() method? Don't know if primitive types are mapped to their Object equivalents (e.g. int to class Integer), but if they are, then you might be able to do something like this, instead of laboriously checking each possible class.
for (String key : bundle.keySet()) {
saveKeyValueInPrefs(key, bundle.get(key).toString()); //To Implement
}
Not sure if this would work for your needs, but I'm trying to do something similar to convert a bundle into a JSON string right now.
I would do it through reflection, if I were to do it at all. Store a static Map such that String.class maps to SharedPreference.putString(), etc. Then, when you're looping through the items check their class against the map. If it doesn't exist, check the superclass, etc. That will either give you the proper method to call or will let you know that the requested object's type isn't something that can be put into the preferences.
So the basic algorithm is:
Get the object from the bundle
Get its class
See if the class is in the map
If it is, invoke the specified method to put it in the SharedPreferences
If it isn't, get it's superclass and return to step 3.
If you get all the way up to java.lang.Object then you've got a bundled object that can't immediately be stored in SharedPreferences. Depending on what classes you've hit along the way you might want to try to handle this as well or you might just want to record the error and move on. Without knowing why you're doing this, it's impossible to guess how you should react when the method fails. It invariably will unless you've got total control over both the bundle and the preferences, but if you've got that amount of control there's no need to jump through all of these hoops because you could be much more straightforward and simply define your own keys.
Note: reflection isn't fast and it isn't the easiest thing to code and maintain. If at all possible I'd recommend finding a less generic method that fits your use case.