I'm writing an Android program I put a ImageView on screen and then remove it but another part of the code is still trying to detect the ImageView after it has been removed. How do I write an if statement that will allow me to detect if the imageView has been removed? I've tried a few things but get no result
if (arrowObj000.get(6).findViewWithTag(arrowObj000.get(6))!=null) {
}
arrowObj00 is a list object/array holding refrences to the ImageView this isn't the problem though
Problem is I need to write an if statement that detects if the ImageView is currently attached.
Walk up the chain of parents, comparing each to the root view of the activity/fragment. If you hit the root, you're attached. If you find a null first, you aren't.
Although a better way to handle this would probably to store the state information somewhere and not use your view as state.
After thoroughly looking through the code hints I found the answer
if (arrowObj000.get(6).isAttachedToWindow()) {
}
Related
I'm repairing my friend's code and got confused.
My friend wants to fetch entered text (in EditText). Seems easy, right? Well, it is but instead of user input, he gets this warning/error:
To be honest I'm not sure how to fix it. He is coding in Kotlin (Android 10).
Activity that contains EditText:
And XML:
This is how it looks when debugging:
The app started working just fine after running "File -> invalidate Cashes/Restart" option, I just don't understand where this warning came from and how to fix it because the error remained unchanged (even though the app works). Do you have an idea how to solve it?
All the best!
fyi lambda expression like setOnClickListener from kotlin is not debuggable, see here.
if you want to debug variables inside setOnClickListener you should use the normal one e.g. setOnClickListener(object: View.OnClickListener {..})
sometimes there will be problem in auto generated binding files, if so it will be solved after invalidate cache and restart ide. sometimes the warning/error show but the project and complied without errors. so no need to worry about that. for next time post the code as code not screen shots.
I understand that the question is regarding evaluating expression, but there is a way you can read variables from your debugger console, even if you're inside an anonymous callback. I found it helpful sometimes. Here are the steps:
First enter debugger mode inside of your anonymous callback,
In your debugger console, look at the right side for "Frames"
Within Frames under , you'll see stack of function execution first top one on the list is the latest:
Click on row(s) below the latest function, until you find an instance of your activity AddInformationActivity. You will see the activity instance on the right side window under Variables. Don't go as far as selecting functions browned out, because those are from internal libraries.
When you see you AddInformationActivity instance, you can expand it and see its variables.
Hope that helps!
It's not a beautiful way, but if you create a method like this:
private fun debug() {
println()
}
and add a breakpoint on the println() it'll capture the activity.
(Don't use TODO as it'll crash the app with a NotImplementedError once called.)
I have this method now in my code all the time to call it whenever I need it.
I know, that question is old, but I just stumbled over it and needed a way.
Let's say we call a method on a variable fetched through findViewById():
TextView tv = (TextView) findViewById(R.id.text);
tv.setText("Some text");
Android Studio automatically warns us that setText() may produce a NullPointerException if tv turns out to be null. If we however are certain that tv will never be null (unless something really wonky happens which should crash the app anyway), is it really worth encapsulating the method call within an if(tv != null){} statement? What if these two (or more) rows are executed very often? Can we gain any significant performance increase?
I personally don't think there is much point in checking these are null because you will know if they are present in your layout file or not, so I wouldn't bother.
However, I do sometimes use the following to prevent the warnings in Android Studio:
assert tv != null;
I don't know how this affects performance but I imagine it will have almost no difference.
Throwing or creating new exceptions will definitely consume more resources than what you might expect BUT it is always good to handle the exception where necessary rather than let the app crash. IF you are absolutely certain that the textview or whatever UI element ISpresent in the correct XML for your activity and/or the fragment then i don't think that you should use try catches at all..
Yes you can use asserts to avoid warning of Android Studio as mentioned above, and with respect to performance I don't think you will notice any huge performance variation. However, its always good to catch exceptions and log them as it can be really useful while debugging.
Actually, it can be null.
If you have complicated layout, and many ids, it can happen if you type id of other layouts.
This is only a warning. If your layout is simple to remember all ids or you sure it's never null, don't bother this warning.
This warning is helpful when you change an id in layout manually.
EX:
layout 1 has ids : text_view_1, button_1
layout 2 has ids : text_view_1, button_2
Activity 2 use layout 2 and findViewById(text_view_1)
If you change from text_view_1 to text_view_2 (MANUALLY by typing). No error happened, because id text_view_1 is still exits. But NullPointerException will occur when you run application.
Whenever we need a reference to the widget, we uses findByViewById.
When we are referring the widget lots of time in the code of the same Activity class, we can follow either of the approach:
Call findViewById every time in Activity lifecycle.
Get it first time, store the reference as a private instance variable of the Activity class.
Which approach is beter? What would be pros and cons of each approach in terms of performance and memory. Please help.
EDIT: If we move to new activity from A to B, we do not finish A as we want to open A on pressing back. In this scenario how to approach above problem? Please help.
Both approaches have their risks. In general, you should call findViewById() the less times you can, by the other hand, storing a reference on the Activity class may lead to memory leaks. It depends so much on what you want to do, how much times are you calling it and basing on it choose one of the approaches. For that, you'll need to analyze your code and if you're not clear about which is better, just try both and choose the "less bad", but generally the first approach is worse than the second one because you know you'll always have to find across ALL elements you've defined an id.
Most developers use method 2, mostly because its more effective. If your layout is complicated then findViewById must traverse its tree to find given widget which takes time. In list views you mostly use ViewHolder pattern which allows you to store references to list item widgets. Since lists are redrawn very ofthen this greatly speeds up its rendering.
Storing widgets in private references is quite safe, those references gets invalidated on configuration changes, but your activity is also destroyed then.
The second possibility is clearly the better.
findViewById iterates through the whole view hierachy, which of course costs much more time than a reference.
Dianne Hackborn (Android engineer) gave some details about the topic here: https://groups.google.com/forum/#!topic/android-developers/_22Z90dshoM
Accessing a member variable is always faster than any function call. The used space for that variable is insignificant.
By the way: The code looks much cleaner!
You should decide this according to your purpose. Holding an object for your views are faster than getting your view with an activity method. But this also means that you are using a memory for your reference and it can cause a memory leak.
I may be wrong since i am new to Android, but i prefer storing a a variable;
it's less coding to write.
for example: if you have to access an imageview that is nested in layouts how would you wish to access it and get its tag.
Access 1:
public Integer getTag(){
FrameLayout frame1 = (FrameLayout) findViewById(R.id.frame_1);
LinearLayout linear3 = (LinearLayout) frame1.findViewById(R.id.linear_3);
ImageView imgView = (ImageView) linear3.findViewById(R.id.myImg);
return Integer.valueOf( imgView.getTag().ToString());
}
Access 2:
private ImageView myImageView;
#Override
public void onCreate( Bundle savedInstanceState){
//set access to variable
}
public Integer getTag(){
//return Integer.valueOf( myImageView.getTag().ToString());
//can be written
Integer mTag = Integer.valueOf(myImageView.getTag().ToString());
return mTag;
}
Things were going well until I switched off the screen lock on my device, then things started going wrong intermittently.
I've managed to track the issue down and have some workarounds in mind BUT I would like to know if there is 'best practice' for avoiding or removing the issue.
The issue:
I have an application which changes images based on the application status.
The images are not huge but quite large (231k~) and are stored as resources.
After several screen rotations (I counted 27 with a project using a single ImageView), loading the images fails with Exception of type 'Java.Lang.OutOfMemoryError'
Stripped down to the barest project, the following demonstrates the problem:
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
// Set our view from the "main" layout resource
SetContentView (Resource.Layout.Main);
//get a reference to the ImageView
var imageView = FindViewById<ImageView>(Resource.Id.imageView1);
imageView.SetImageBitmap( Android.Graphics.BitmapFactory.DecodeResource( this.Resources, Resource.Drawable.Ready) );
}
The above code is the only method I used to reproduce the issue.
Whilst attempting to resolve, I extended the example so that imageView was released in OnDestry:
protected override void OnDestroy ()
{
base.OnDestroy ();
imageView.SetImageBitmap( null );
imageView.DestroyDrawingCache();
imageView.Dispose();
}
This made no difference unless I added GC.Collect() which I don't want to do.
The best workaround I've currently thought of so far would be to modify the code as follows:
static Bitmap _ready = null;
private Bitmap GetReadyImage {
get {
if (_ready == null) {
_ready = Android.Graphics.BitmapFactory.DecodeResource (this.Resources, Resource.Drawable.Ready);
}
return _ready;
}
}
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
// Set our view from the "main" layout resource
SetContentView (Resource.Layout.Main);
//get a reference to the ImageView
imageView = FindViewById<ImageView>(Resource.Id.imageView1);
imageView.SetImageBitmap( GetReadyImage );
}
This relies upon a static reference to each Bitmap and a property accessor for each.
I could even write a method which stores the images in a static List to save writing property accessors for each different property/variable.
I could perhaps add the flags ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize |ConfigChanges.KeyboardHidden) but this would break the normal Activity lifecycle which I've read isn't best practice?
I find it strange that having scoured the web, I've not yest encountered similar issues or examples. I'm left wondering how most others deal with this?
Any thoughts or comments are much appreciated.
I can only approach this problem from a truly native perspective, as I have not worked directly with the Mono framework.
The described symptoms are 100% indicative of a memory leak in the Activity, but the code shows no real evidence. If you can truly produce the issue with a project containing only one Activity and those four lines of code, it sounds to me like it is perhaps a framework bug that ought to be filed with Xamarin. Have you attempted to create the same simple project in pure Java to see how the results fare on the same device/emulator you are using? It would also be interesting to know if the issue is localized to a specific version of Android. I have never seen this particular behavior before in a native application project.
The awkward part is your statement that forcing a garbage collection makes the problem go away. You're right, you shouldn't have to do that, but a true memory leak (i.e. an unreleased reference) would still persist even if you hit the GC several times. The Android paradigm of destroying and re-creating the Activity on each rotation is such that even if the old Activity lived for awhile, when memory was tight it (and all its references) would quickly be collected to make room for a new instance. If this is not happening, and each Activity is living on past even the system triggered GC passes, perhaps there is a stuck reference in the native code generated by Mono.
Interestingly enough, technically your workaround actually does introduce a true leak, by attaching the Bitmap to a static field that is never cleared. However, I agree that in comparison it seems like a more efficient move. A simpler workaround might also be to code your Activity to manually handle configuration changes (I don't know if Mono is different, but this is accomplished by adding android:configChanges="orientation" to the manifest file). This will keep your Activity from being recreated on each rotation, but it may also require you to reload your view hierarchy if you have different layouts for landscape and portrait. However, even if you have to do this the Acitivity instance will be the same you can safely save the Bitmap without resorting to a static field.
However, if you cannot reproduce the problem with the same project in a native Java project, I would report a Mono bug.
Hard to see without the entire code but it obviously sounds like you have a memory leak. Screen rotation (due to the destroying/creation of the activity) is known to cause these. You might want to have a read at this article by Romain Guy as well as this talk from last year's IO.
I want to know is there any method or any link or tutorial to perform redo undo operation in Android edittext. If any one knows than please let me know.
Quick note on the Antti-Brax/Divers(Kidinov) solution. It works great, except if you try to use it with a TextView post-API 23, you'll run into problems, because guess-what, Google actually added a hidden UndoManager (android.content.UndoManager) and didn't document it or make it obvious it was there. But if you have a hard/bluetooth keyboard in Marshmallow or Nougat and hit ^Z or SHIFT-^Z, you'll get undo/redo.
The problem comes if you're already using Antti-Brax's class with an EditText, and you also hook it to ^Z and shift-^Z, you'll run into problems with anyone using a hard keyboard. Namely the ^Z will trigger BOTH the native and Antti-Brax's undo, leading to two undos simultaneously, which isn't good. And after a few of them, you'll probably get a Spannable out of bounds crash.
A possible solution I found is to subclass the TextView/TextEdit/whatever and intercept the undo/redo calls from the TextView so they don't run as follows:
#Override
public boolean onTextContextMenuItem(int id) {
int ID_UNDO, ID_REDO;
try {
ID_UNDO = android.R.id.undo;
ID_REDO = android.R.id.redo;
} catch (Resources.NotFoundException e) {
ID_UNDO = 16908338; // 0x1020032
ID_REDO = 16908339; // 0x1020033
}
return !((id == ID_UNDO) || (id == ID_REDO)) && super.onTextContextMenuItem(id);
}
Those magic id numbers were found here, and are used only as a backup if the android.R.id.undo values aren't found. (it also might be reasonable to assume that if the values aren't there the feature isn't there, but anyway...)
This is not the best solution because both undo trackers are still there and both are running in the background. But at least you won't trigger both of them simultaneously with ^Z. It's the best I could think to do until this gets officially documented and the getUndoManager() methods of TextView is no longer hidden...
Why they made a feature you can't turn off (or even know if it was there or not) "live" in released Android I can't say.
I just opened an issue on Android's issue tracker if anyone wants to follow this.
There is an implementation of undo/redo for Android EditText in
http://credentiality-android-scripting.googlecode.com/hg/android/ScriptingLayerForAndroid/src/com/googlecode/android_scripting/activity/ScriptEditor.java
The code works but does not handle configuration changes properly. I am working on a fix and will post here when it is complete.
My Google search was :-
android edittext onTextChanged undo
I know this is an old question, but as there is no accepted answer, and this is an issue I've tackled myself from many angles, I'd like to add my solution in case it helps anyone. My answer is probably most relevant to large (1,000words+) volumes of text editing apps that require this feature.
The simplest way to resolve this problem is to make periodic copies of all text on screen, save it to an array and call setText() every time the Undo method is called. This makes for a reliable system, but it isn't ideal for large (i.e. 1,000words+) text editing apps. This is because it:
Is wasteful. It could be that only one word changes in a two thousand word document, so that's one thousand, nine hundred and ninety nine words needlessly committed to memory.
Can lead to performance issues, as some low-tier hardware struggles with rendering large amounts of text. On some of my test devices, this method can lead to freezes of a few seconds whenever Undo is called.
The solution I currently use is comparatively complex, but I've published the results in a library here.
Essentially, this library saves a copy of text as soon as a user begins typing, and then another copy of text once they've stopped typing for a set amount of time (in my case, two seconds). The two text strings are then compared, and the altered section of text returned, the indexes where the alterations occured, and details on whether or not the change was an addition of new text, a deletion, or a replacement of old text with new text.
The net result is that only the necessary text is saved, and when Undo is called, there is only a local delete(), replace() or insert() call, which makes for much faster operations on large text fields.
Here is the undo/redo implementation that was linked to from Gary Phillips' answer extracted into a reusable and universal undo/redo plugin for any widget that descends from a TextView. I added some code for persisting the undo history.
http://code.google.com/p/android/issues/detail?id=6458#c123
Hope this helps.
To preserve EditText Styling with regards to undo:
You can create an ArrayList<EditText> or ArrayList<String> (String containing html text) to store your last 10 (for example) actions. So ArrayList [0] would contain html text from your first action and ArrayList [9] would contain html text from your very last action. Each time the user taps "undo" in your app, you would apply ArrayList [size()-1] to your EditText and then remove ArrayList [size()-1] from your Array.