Reputation: 195
I am inflating layout in onCreate() which is already declared in my activity:
layout = (RelativeLayout) findViewById(R.id.layout);
Assume id is declared as an int in my activity.
Later, after some event I am adding an imageview to this layout
id = (int) Calendar.getInstance().getTimeInMillis();
ImageView imageView = new ImageView(context);
imageView.setImageResource(R.drawable.ic_launcher);
imageView.setId(id);
layout.addView(imageView);
Later somewhere, I want to get imageView from the id we have set earlier:
ImageView imageView = (ImageView) findViewById(id);
if (imageView == null)
Log.e("Test", "imageview is null");
All code runs successfully and Imageview always returns null as printed in log.
Note: I can't able to keep the object of imageview itself because I have many number of different views in real project. Here I have described my problem using single imageview. I have stored all the ids of the views but can't able to get all those views using findViewById(). The reason why I have used Calendar.getInstance().getTimeInMillis() to generate id is because I want a unique id everytime. I have stored all the layout data including ids for later use. If user again opens this activity anytime, he will get from where he left off. So while adding any new imageview the id must not be repeated which is generated earlier.
Keypoint: If I set the device date-time 2-3 or more days earlier then it is worknig properly. I think the issue is with generating the id using calendar.
Upvotes: 0
Views: 944
Reputation: 37798
Okay so I went and look around with the community and seen posts on how to dynamically add an id in R.id
for use by findViewById()
. At first I thought you should go ahead and use View.generateViewId()
but as you commented in one of the answers, you don't prefer to use that. So I went with your implementation and tried it out, added in some logs and such. First, here is my simple activity code:
MainActivity.java
package com.example.my.myapplication;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.ImageView;
import android.widget.LinearLayout;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LinearLayout llmain = (LinearLayout) findViewById(R.id.ll_main);
int id = (int) System.currentTimeMillis();
Log.d("SAMPLE", "Generated ID: " + id);
ImageView imageView = new ImageView(this);
imageView.setImageResource(R.drawable.sample_img);
imageView.setId(id);
llmain.addView(imageView);
Log.d("SAMPLE", "Get ID: " + imageView.getId());
ImageView iv = (ImageView) findViewById(id);
if (iv == null) {
Log.d("SAMPLE", "ID: IMAGE VIEW IS NULL!");
} else {
Log.d("SAMPLE", "ID: ImageView not null!");
}
}
}
So I went and tried it out.. Here are the logs..
03-18 10:54:47.907 29562-29562/com.example.my.myapplication D/SAMPLE: Generated ID: -2019192733
03-18 10:54:47.913 29562-29562/com.example.my.myapplication D/SAMPLE: Get ID: -2019192733
03-18 10:54:47.913 29562-29562/com.example.my.myapplication D/SAMPLE: ID: IMAGE VIEW IS NULL!
Then I saw from the docs of setId():
The identifier should be a positive number.
Notice that the id generated was negative before. So I went and changed the id generation to this:
int id = Math.abs((int) System.currentTimeMillis());
And tried running it again, here are the logs:
03-18 10:58:05.073 32662-32662/? D/SAMPLE: Generated ID: 2018995567
03-18 10:58:05.080 32662-32662/? D/SAMPLE: Get ID: 2018995567
03-18 10:58:05.080 32662-32662/? D/SAMPLE: ID: ImageView not null!
Notice that the id now generated is positive. Now it is able to identify it somehow.
Upvotes: 0
Reputation: 195
Finally, I got the solution using try and error.
As I have mentioned that it was working properly before 2 days, I have decided to debug using the id generated and casted from long
to int
by decreasing the date every time. Assume counter is declared as an int
in activity.
ImageView imageView = new ImageView(context);
imageView.setImageResource(R.drawable.ic_launcher);
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.DAY_OF_MONTH, calendar.get(Calendar.DAY_OF_MONTH) - counter);
counter++;
String date = getDate(calendar.getTimeInMillis(), "dd/MM/yyyy hh:mm:ss.SSS");
Log.e("Test", "Date :" + date);
int id = (int) calendar.getTimeInMillis();
Log.e("Test", "ID:" + id);
imageView.setId(id);
layout.addView(imageView);
imageView = (ImageView) findViewById(id);
if (imageView == null)
Log.e("Test", "imageview is null");
else
Log.e("Test", "not null");
Logs:
03-17 23:13:44.952: E/Test(1469): Date :17/03/2016 11:13:44.952
03-17 23:13:44.952: E/Test(1469): ID:-2018055688
03-17 23:13:44.952: E/Test(1469): imageview is null
03-17 23:13:48.744: E/Test(1469): Date :16/03/2016 11:13:48.745
03-17 23:13:48.744: E/Test(1469): ID:-2104451895
03-17 23:13:48.748: E/Test(1469): imageview is null
03-17 23:13:53.376: E/Test(1469): Date :15/03/2016 11:13:53.380
03-17 23:13:53.376: E/Test(1469): ID:2104120036
03-17 23:13:53.376: E/Test(1469): not null
Here, I found that I get negative int from last two days and before that I am getting positive int. As mentioned in the doc that you should set id to positive int. Then I have converted same id to absolute value using:
id = Math.abs(id);
and all works fine.
Finally, I am wondering why setId()
is not giving exception if set to non-positive int
. They should give exception as they have mentioned that it should be postive int so any developer come to know what is the problem.
Upvotes: 2
Reputation: 18112
If you don't provide container from which you need to find the view like View v = findViewById(id)
then this is would try to find the view in the used xml.
Do this
ImageView imageView = (ImageView) layout.findViewById(id);
if (imageView == null)
Log.e("Test", "imageview is null");
Note:
Use this to generate the id dynamically
int id = System.currentTimeMillis();
getTimeInMillis()
Returns the time represented by the Calendar, recomputing the time from its fields if necessary. If the time is not set and the time cannot be computed from the current field values. This might be the case for you and you must not be getting the milliseconds.
Upvotes: 1
Reputation: 2082
When generating id programatically you should use following code to set id of a view,
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
myView.setId(Utils.generateViewId());
} else {
myView.setId(View.generateViewId());
}
Can you use this to set id and test it?
Upvotes: 0