Android: setImgVisibility() error - android

In my app I have a header with icon hidden, I have a adapter with a listview when I click the listview I go to a login screen using listener, when the login is successful is should come back to listview(adapter) and icon should get visible on header.
In the login activity I have the following code:
public void onClick(View v) {
String password = etPassword.getText().toString();
if(password.equals("guest")){
SearchAdapter.setImgVisibility();
} else {
//-----
}
finish();
}
In my adapter I am calling the setImgVisibility() as follows, but it is not working
public static void setImgVisibility() {
img.setVisibility(View.VISIBLE);
}
I am getting a Nullpointerexception near the line img.setVisibility(View.VISIBLE);
I am stuck here and don't know what I am doing wrong. Any suggestions or help is appreciated

I would imagine that img is null. You need to look at where this value is set and make sure happens before you call the method setImgVisibility.
Show more of your complete code for people to help further.
Additionally, i've just noticed you've used a static reference to your search adapter, you should be really careful using statics, especially where any referencing of images is concerned as images can be bound to the context, as such unless you nullify the static you will end up with a memory leak. (this used to be an old problem, not sure its still valid, but i would still avoid using a static reference).
Without more code we're not likely to be able to properly help you. For example are you switching activities when logging in? If you are, this won't work at all.
[given the comment below] If you switch activities then your activity containing the list view is going to be destroyed and then rebuilt then you navigate back to it. or it will at least go through the activity lifecycle. This means you can set the icon during the instantiation of the header img.
You could store your logged in state as a property of the Application or a preference. Grab this value when you set the header image and set the image accordingly.

your img object is null. Is your img object is same as View v then you can pass v in setImgVisibility() and then set v.setVisibility(View.VISIBLE)

Related

android kotlin click listener loses its "click methods" after some time

Hi I'm implementing click listeners in the following way but after some time the methods and variables inside the listener's closure get the wrong values or something. Let me explain the implementation of the listener a little better a for loop creates the listener for a set of image views then later in the program the for loop is called a second time and it resets the listener methods and variables to different values. Everything works great for about 30 minutes but then for some reason, the listener's methods and variables start having the wrong values. Has anybody ever heard of this behavior or can tell me where I've gone wrong with the code? Keep in mind that the listener I'm about to paste here is just a small piece of a 1014 line class. I'm hoping somebody can spot How I'm implementing the listener wrongly and can give me some advice on how to "reset" the listener so that it's variables and values stay over time. Hopefully you can read the code without putting it in an editor but feel free to copy it for readability's sake Here is the code for the image view listener with comments.
//image views are held in an array
//set an image view in its imageview container
imgArr0[slotId1].invalidate()
imgArr0[slotId1].setImageDrawable(null)
//drw is not defined in this example
imgArr0[slotId1].setImageDrawable(drw)
/*if video or image id is set to image then set a listener for the image
*/
/*slotId1 is not defined in this example but it is simply a counter to iterate over the ImageView array
*/
if (videoOrImageId0[slotId1] == "image") {
//null any listeners that might be attached to the image view
imgArr0[slotId1].setOnClickListener(null)
//set or reset the listener
imgArr0[slotId1].setOnClickListener() {
`enter code here`//if the current config is portrait then set a new image image
if (currentConfig0 == "portrait0") {
act0.lrgImage0.invalidate()
act0.lrgImage0.setImageDrawable(null)
/*drw is not defined in this example but works fine in the production script
*/
act0.lrgImage0.setImageDrawable(drw)
}
--calmchess
ccc tv application with problem.
(https://i.stack.imgur.com/PjdbN.jpg)![enter image description here](https://i.stack.imgur.com/FaMnc.
I was able to partially solve this question by destroying all the image views and their associated click listeners then rebuilding those... However I don't consider this issue completely solved so if anybody can provide a better solution I'd love to hear it because rebuilding the images every few minutes has to be using a lot of unnecessary hardware resources.
--calmchess

How to change textviews & imageviews of another activity in Android

I have an activity which can take a few seconds to load its content (mainly pictures) from the cloud. Let's say this content is pictures & description from a person. The user can go to pictures & description from another person by clicking on the next button. I'd like to avoid the loading time When this button is clicked.
To do this I have two activities : firstPersonActivity for the first person content, and secondPersonActivity for the second person content.
What I try to do is to load the content of the secondPersonActivity when the user is in the firstPersonActivity, so that the secondPersonActivity can be displayed "directly" (= without needing to load content from the cloud when the next button is clicked in the firstPersonActivity).
But I do not succeed in doing this, I don't know how to modify the views of the secondPersonActivity layout from the firstPersonActivity class.
I tested the following code in my firstPersonActivity but it doesn't work (there is no connexion to the cloud, it's just a test to better understand how it works). R.id.first_image_second_person is the id of my imageview in the secondPersonLayout (= the layout used in the secondPersonActivity).
ImageView firstImageSecondPerson = (ImageView) findViewById(R.id.first_image_second_person);
firstImageSecondPerson.setImageResource(R.drawable.mypicture);
When I click on the next button to go from the firstPersonActivity to the secondPersonActivity, my firstImageSecondPerson imageview is not filled.
Do you see what's wrong ?
Is there a better way to avoid the loading time when the user click on the next button ?
It is not possible to change activity if activity instance is not created. In my opinion to do what You need I would go to single activity with hidden content of second person ( VIEW.INVISIBLE ) and show/hide it when it is needed.
But if second activity must be there, then create some structure for saving bitmaps in memory. In Your code sample You get picture from drawable so we are not talking about some delays, but if images are downloaded from some server then You can create some class which will have those bitmaps created from url and instance of this class can be used on any activity.
So for example Your class for caching pictures would have some method for creating bitmaps like -How to load an ImageView by URL in Android?. And those bitmaps should be saved in some Array or HashMap to have access to it, for example ( pseudo code ):
//some structure for cashing pictures in app
class PictureCache {
static PictureCache instance;
final HashMap<Integer, Bitmap> bitmaps;
//singleton
static PictureCache getInstance(){
if (instance==null)
instance = new PictureCache();
return instance;
}
public PictureCache(){
bitmaps = new HashMap<>;
}
private Bitmap loadBitmap(String url);//#1
public addPicture(Integer personId, String href){
//add to hashMap
bitmaps.put(personId, loadBitmap(href));
}
public Bitmap getPicture(Integer personId){
return bitmaps.get(personId);
}
}
#1 - method from How to load an ImageView by URL in Android?
Using it in first activity:
PictureCache.getInstance().addPicture(12,"http://url.to.bitmap");
Using it in second activity:
Bitmap pic = PictureCache.getInstance().getPicture(12);
Important note - above code was written here and was not tested, it shows solution concept.
Important second note - using such approach with bitmaps in memory can cause to much memory usage
You cannot access the views of SecondActivity before its creation. If you called this activity once only then you are able to access its views by making them static.
One more Solution for this is..
Access the whole data at once and save it in static arraylist with the help of getter-setters. Then on SecondActivity set data from that arraylist.
Hope this will work.
I don't think you can access the view before creating the activity.
You can try to use Glide for caching your images and minimizing loading time.
Try this
Picasso.with(getContext()).load(R.drawable.generatedId).into(imageView);
or
imageView.setImageDrawable(ActivityCompat.getDrawable(getContext(),
R.drawable.generatedID));`

Static Bitmap set to null doesn't stay null

In my app I have a profile pic of the user. If he previously logged in, I download it from my server, otherwise he takes a pic from the camera or gallery. Either way, I store it in a class called DataStorage in a static public Bitmap variable thus:
public class DataStorage {
.
.
public static Bitmap origProfilePic; //not saved on app close
.
.
Now, if the user decides to re-do his profile, I log him out send him back to the profile creation screen, and I call:
DataStorage.origProfilePic = null;
(By the way, null is a legitimate value for this picture - we allow users to have no picture). The profile creation is through 2 activities - first choosing a username and password, then choosing a picture and other details. What's weird is that although I set the picture variable to null, somehow when I get to the end of the profile creation, it has gone back to it's original value, and I somehow have a user with the old profile picture (this is in the case where he did not select a new picture)
I've logged it n the OnCreate functions of the two activities:
onCreate SignUpActivity1, origPic = null
then
onCreate SignUpActivity2, origPic = android.graphics.Bitmap#42ba7438
But SignupActivity1 calls the intent for SignUpActivity2 and nowhere in SiugnupActivity1 is there a reference to DataStorage.origProfilePic except in my log statements.
I decided to check one more time in SignUpActivity1 if the value changes and I found...just as I invoke SignupActivity2:
Intent intent = new Intent(SignUpActivity1.this, SignUpActivity2.class);
intent.putExtra("EMAIL", email.toString());
intent.putExtra("PASSWORD", password.toString());
startActivity(intent);
Log.e("Kibi", "End SignUpActivity1, origPic = " + DataStorage.origProfilePic);
finish();
This somehow has:
End SignUpActivity1, origPic = android.graphics.Bitmap#42ba7438
This is quite repeatable in this specific case, though I certainly set the bitmap to null in other places and don't see it popping back up.
I saw a few things on SO about static Bitmaps being a danger for memory leaks, though I don't see a memory leak right now, I worry that I must be doing something very wrong if setting to null cannot be relied upon.
Can anyone explain what I am doing wrong and what the best way is to store this Bitmap in a basically volatile way?
It makes sense that both values change when you use DataStorage.origProfilePic in both activities. Since it's a static value, both activities are pointing to the same memory object.
DataStorage.origProfilePic is pointing to a piece of memory where your bitmap is stored. Assuming you use something like:
#SignUpActivity1
Bitmap origPic = DataStorage.origProfilePic;
#SignUpActivity2
Bitmap origPic = DataStorage.origProfilePic;
What happens here is that you create a reference to DataStorage.origProfilePic. That means you practically have the same value in SignUpActivity1.origPic and SignUpActivity2.origPic.
When you call this rule:
startActivity(intent);
The OnCreate method in SignUpActivity2 will be invoked. You probably will set here (or somewhere else) the value of DataStorage.origProfilePic, which means the value of SignUpActivity1.origPic and SignUpActivity2.origPic also changed (not entire true, but will have a different output).
Also be carefull with DataStorage.origProfilePic = null;. This only set the reference to null, but doesn't clear the bitmap from memory. Use DataStorage.origProfilePic.recycle(); to clear the bitmap from memory.

Android: reference to a dynamic View is no longer valid after screen rotation

Context:
i have n dynamically created ImageView(s) in an activity.
when an imageview is touched:
1) an IV object reference is stored vis the onTouch event.
2) a dialog opens; allowing the user to edit the image.
when the user has finished making edits, the changes are applied to the object which we have a stored reference.
however, if the user rotates the device while the Dialog is open, the activity is recreated; and the reference to the selected ImageView is no longer valid.
Issue:
So, the problem is that the recreated ImageView, produced from the rotation event, has a different reference to the reference that i have stored, meaning that i have no idea which ImageView to apply my edits to..
This seems like a common issue that could easily be solved, but i don't know how..
because the ImageView(s) are dynamically created, and there could be n quantity, i can't find view by ID.
i can't set a tag, as it is lost when the IV is recreated.
i read something about retainInstanceState, but this appears to be for fragments; not activities
Assign ids to your generated ImageViews. When dialog is shown you pass this id to dialog, when dialog finishes it returns your values and this id, then you just get ImageView by id, be it a new one, or old doesn't matter since the couple 'id - iv at position' are the same no matter how many times you recreate activities.
As example:
for (int i=0;i<20;i++) {
ImageView iv = new ImageView(context);
iv.setId(1337 + i); // Spice things up a little :D
addView(iv);
}
Then just pass required id iv.getId() to dialog, and when dialog finishes get iv by calling findViewById(id);
The easiest way to fix this is to add android:configChanges="orientation|<whatever other flags you need>" to your <activity> in AnroidManifest.xml, so the activity won't be recreated when orientation changes. However, using this method is officially discouraged:
Note: Using this attribute should be avoided and used only as a last resort
Another way would be to store in the dialog not the reference to ImageView, but its id instead.

Issue with Android fragments: getView() returns null

Our app has several fragments. In one of them user fills several TextEdit fields. When he finishes he presses a button in the ActionBar to save the data. The Action just calls a private method named "saveData" that fetches all data from the fields and submit it to our server.
We have many stack traces from our users showing that getView() returns null in method saveData, but for just a small part of them. For most of them there is no problem at all. We cant reproduce the problem and we cant understand what might be causing it. The code is pretty simple:
View vw = this.getView();
EditText et;
et = (EditText)vw.findViewById(R.id.editEmail);
String email = et.getText().toString().trim();
et = (EditText)vw.findViewById(R.id.editPassword);
String password = et.getText().toString().trim();
The action is added in osResume, see below:
public void onResume() {
super.onResume();
MainActivity act = (MainActivity)this.getActivity();
act.bar.removeAllActions();
act.bar.addAction(new SaveAction());
}
Any ideas? How can we reproduce it?
Can you tell from your logs whether the problem is always for the same users / devices ?
I see from the code that you have submitted that the view is in the same fragment - is that actually the case ?
It's POSSIBLE that a fragment no longer in view can have their view destroyed in order to free up resources. e.g.
getView() returns null
If I suspected that this might be the case then I would attempt to recreate the problem on a phone / tablet / emulator with limited resources.
Good luck !

Categories

Resources