Brijesh Chopda
Brijesh Chopda

Reputation: 195

findViewByID returns null after setting same id to the view

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

Answers (4)

AL.
AL.

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

Brijesh Chopda
Brijesh Chopda

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

Rohit5k2
Rohit5k2

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.

Official doc

Upvotes: 1

baldguy
baldguy

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

Related Questions