What is resource:0 doing? - java

I didn't understand what is the use of 0 here.
What exactly it is doing?
public WordAdapter(Activity nmbersActivity, ArrayList<Word> word) {
super(nmbersActivity,0,word);
}
And i have check the documentation and can't find exactly what it is.
In the implementaion this is the code.
public ArrayAdapter(#NonNull Context context, #LayoutRes int resource,
#NonNull List<T> objects) {
this(context, resource, 0, objects);
}

From the docs:
The id of the TextView within the layout resource to be populated
ArrayAdapters are commonly used in lists so a text resource id is included to display the item title. Passing 0 signifies the default state of no TextView resource.

Related

Meaning of this in Java (currently in Kotlin)

I am looking at a class which goes like this:
class temp(context: Context, attrs: AttributeSet) :
LinearLayout(context, attrs), tempInterface {
..................................
}
I just wanted to ask, how can I translate this to Java? I have been able to do this as of now:
public class temp extends LinearLayout implements tempInterface
....................
public temp(Context context, AttributeSet attrs) {
super(context, attrs);
}
....................
}
In the Kotlin version, I see that LinearLayout is also accepting two attributes (context and attrs) whereas in Java version I see I have only defined the constructor for the primary class, i.e. temp. Is that okay?
What you wrote is exactly equivalent to the Kotlin code. There are several ways to valide this.
Use Kotlin decompiler
You can copy the Kotlin code into a project that has Kotlin set up (you can find working samples), then open it in IntelliJ IDEA or Android Studio.
There's a menu item: Tools > Kotlin > Show Kotlin bytecode, and then there's a Decompile button on it.
Executing this flow gives the following output:
public final class temp extends LinearLayout implements tempInterface {
public temp(#NotNull Context context, #NotNull AttributeSet attrs) {
Intrinsics.checkNotNullParameter(context, "context");
Intrinsics.checkNotNullParameter(attrs, "attrs");
super(context, attrs);
}
}
This is the exact code that Kotlin compiles to.
Ask ChatGPT to translate it
This is perfect for ChatGPT's capabilities, rather than asking here on SO. I tried it myself with prompt: "here's some Kotlin code, translate to Java: <code>" and it gave an almost perfect translation of the Kotlin code back to Java. It just missed public on class.
Look at documentation
This being said, you probably want to create a custom view/layout in Android using the Java language. You can see the example code and other documentation here: https://developer.android.com/develop/ui/views/layout/custom-views/create-view#subclassview
If you swap between Java and Kotlin just above the code block you can find a very similar example to yours.
Generate code from template in Android Studio
Note that usually you need 3 constructors, this is shown by looking at the code generated in Android Studio:
public class MyView extends View {
public MyView(Context context) {
super(context);
init(null, 0);
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs, 0);
}
public MyView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(attrs, defStyle);
}
private void init(AttributeSet attrs, int defStyle) {
...
}
}
You can use Android Studio's File > New > UiComponent > Custom View. Note that this action is context sensitive, make sure you're inside a Java or Kotlin file in an Android module, or right clicks src/main/java or src/main/kotlin to be sure.

How to create a reusable RecyclerView using "Composition over Inheritance"?

One of my coworkers created an inherit from a RecyclerView and added the logic to create its adapter, defined custom list item attributes, and layout manager inside it.
This is an example of his idea:
class CustomRecyclerView #JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : RecyclerView(context, attrs, defStyleAttr) {
init {
loadCustomAttributes()
setDefaultAdapter()
setDefaultLayoutManager()
}
private fun loadCustomAttributes() {
// Load custom attributes: item background, for example.
}
private fun setDefaultAdapter() {
// Define specific Custom Adapter.
}
private fun setDefaultLayoutManager() {
// Define specific Layout Manager.
}
fun setData(data: List) {
// Set data and notify dataset changed.
}
private class CustomAdapter : RecyclerView.Adapter<CustomAdapter.ViewHolder>() {
// Specific Adapter.
}
private class ViewHolder(private val view: View) : RecyclerView.ViewHolder(view) {
// Specific View Holder.
}
}
I understand his reasons, and it's very reasonable: he wants to plug a View on the XML and just reuse it, without defining the adapter or anything else on the Activity or Fragment; he will just set the data with the method "setData".
But on the other way, I feel that this class is inheriting a RecyclerView just to breaking the design of the RecyclerView and giving too many responsibilities to it. My pain points are:
A RecyclerView shouldn't decide an item attribute (item background colour, for example);
A RecyclerView shouldn’t know about his LayoutManager;
A RecyclerView shouldn't have methods to update the data on the adapter;
A RecyclerView shouldn’t create an instance of his Adapter.
This is an "inheritance over composition" approach.
I tried to find information about it on the internet, but I didn't find anything about good practices when inheriting from a ListView/RecyclerView.
Another idea would be to wrap it inside another layout (ViewGroup or FrameLayout) to encapsulate it. But this would create an unnecessary nested layout, and it will be complicated to test using Espresso (because now the list is private and shouldn't be exposed).
My question is: how to create a reusable RecyclerView using "Composition over Inheritance"?

android 2 way data binding example don't work as described

I read this article about 2 way android data binding
I noticed that code is a bit vague and decide to implement workable example and put it on github, so other guys will be much easier to dive in it. But going according instructions provided in this article I wasn't able make it work.
In my example I just have main activity with switcher, and custom control, also with switcher. So, when I checking main switcher it refresh all the stuff properly and work as expected, but however when I check/uncheck internal switcher, it dosen't affect main viewmodel and anything in activity - so 2 way binding not working.
Please, help me find the reason why this happen and fix the problem.
Code fixed and now worked as expected in Android Studio 2.2 beta 1 at least.
Link to the code sample on github
You almost hooked up everything properly. In CustomSwitcher, there was no notification when the inner switcher's value changed. You must listen for that change and call the onValChanged callback.
Here is your code:
public CustomSwitcher(Context context, AttributeSet attrs) {
super(context, attrs);
this.binding = CustomSwitcherBinding.inflate(LayoutInflater.from(context), this, true);
}
public void setVm(boolean vmVal){
this.vm = vmVal;
this.binding.setItem(vm);
}
The inflated binding doesn't directly notify the custom switcher, so you must listen for the event. Then you'll have to call the listener. You must also avoid the infinite loop of notifying the same value over-and-over again by assuring that you're not setting the same value as already exists.
public CustomSwitcher(Context context, AttributeSet attrs) {
super(context, attrs);
this.binding = CustomSwitcherBinding.inflate(LayoutInflater.from(context), this, true);
this.binding.addOnPropertyChangedCallback(new Observable.OnPropertyChangedCallback() {
#Override
public void onPropertyChanged(Observable sender, int propertyId) {
if (propertyId == BR.item) {
setVm(binding.getItem());
}
}
});
}
public void setVm(boolean vmVal){
if (vmVal != this.vm) {
this.vm = vmVal;
this.binding.setItem(vm);
if (this.onValChanged != null) {
this.onValChanged.onValChanged(this, vmVal);
}
}
}

How to instantiate multiple custom views in Android?

I'm really confused about custom views.
I need to define a custom view, consists of an ImageView and a TextView. And then I want to change the contents of this views, according to a php json response, which I have accomplished.
First of all, which way should I go :
1) Define the custom view as an XML, then "inflate" , duplicate, whatever, and then change the newly instantiated text's and image sources etc ?
2) Define the custom view as a Java class, and instantiate it ?
In the end, I want to instantiate my custom views as children of a vertical layout.
What I'm currently trying is, path #2. I defined this class :
public class ArizaSatiri extends LinearLayout {
TextView arizaTitle;
//constructor :
public ArizaSatiri(Context context, AttributeSet attrs)
{
super(context, attrs);
// add title , description etc :
arizaTitle = new TextView(context);
arizaTitle.setText("abcef defefef");
this.addView(arizaTitle);
}
}
Then I tried this in my main activity :
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_arizalarim);
ArizaSatiri as = new ArizaSatiri(getApplicationContext(), attrSet);
}
But I have no idea how to construct an AttributeSet.
So please tell me, which path should I choose, and how to accomplish to instantiate a custom view, as many times as I want, dynamically ?
Attribute set is constructed when you add your component via xml. You have to define custom component's attributes in attrs.xml. (http://www.vogella.com/articles/AndroidCustomViews/article.html#additional_attributes)
If you do not want to create your view from xml then just remove attribute set from the constructor as LinearLayout has a constructor without the attr set: http://developer.android.com/reference/android/widget/LinearLayout.html#LinearLayout(android.content.Context)

Why can't I use Resources.getSystem() without a Runtime error?

public class BobDatabase extends SQLiteOpenHelper{
private static final String DATABASE_NAME = "bob.db";
private static final int DATABASE_VERSION = 1;
public static final String DEFAULT_PROFILE = "default_profile";
public BobDatabase(Context context)
{
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase database)
{
createProfileTable(database);
createTimeTable(database);
createEventTable(database);
createLocationTable(database);
}
/**
* Creates a table for Profile objects, executes the string create_profile_table_sql
* contained within strings.xml
* #param database
*/
public void createProfileTable(SQLiteDatabase database)
{
database.execSQL(Resources.getSystem().getString(R.string.create_profile_table_sql));
}}
I get this error
01-14 12:20:57.591: E/AndroidRuntime(1825): Caused by: android.content.res.Resources$NotFoundException: String resource ID #0x7f040003
The code that causes the error is the single line inside createProfileTable specifically, Resources.getSystem().getString(R.string.create_profile_table_sql) if I use a class variable to hold a Context and do context.getString(R.string.create_profile_table_sql) I don't get any errors but I don't want to do that because I want to avoid memory leaks and according to what I know this should work. Any idea what's happening?
According to Android documentation, Resources.getSystem() only provides system-level resources, not application-level ones (like the resources inside your strings.xml file).
http://developer.android.com/reference/android/content/res/Resources.html#getSystem()
Try using the application's context if you really want to retrieve your strings this way, or take my suggestion in the comment to your question.
Using Resources.getSystem().getWhatEver() you can only access system-wide resources (you get the error because there is no system-wide resource with your ID). Since resource ID are not unique across applications you need to provide the application, when accessing a resource. In Android this is done using Context.
So if you want to access some resource you need to use it like this
context.getResources().getString(myID);
Apart from that Brandon's comment is correct.
You could get the context parametr in the function by parameter, or by a static variable, or by getApplicationContext() function.

Categories