当前位置:网站首页>Various pitfalls encountered in UI development
Various pitfalls encountered in UI development
2022-07-28 14:43:00 【Sharp surge】
1
The soft keyboard hides problems
Problem description :Activity Press return to call finish() After the method , The interface has been destroyed , But the soft keyboard is still on the screen , This makes the currently displayed Activity You can't see it without an input box , Very serious visual impact .
Try to plan : Find various ways to hide the soft keyboard , All kinds of search on the Internet . The idea is when the activity exits , Would call onDestroy() Method .
Destroy interface , Find a way to hide the interface in this method . Find this way , But still not . I've also tried to find all of them with base classes edittext Then let them lose focus , Hide soft keyboard , It turned out to be useless , Debug and solve it quickly !

Solution : At the beginning onDestroy() The idea of hiding the soft keyboard in the internal key is wrong , because onDestroy() There are two other life cycle methods , There is a method like the above to hide the soft keyboard getCurrentFocus(), stay onDestroy() You can't get the right control to get the current focus before . So in onPasue() It is effective to hide the soft keyboard in the method , stay onDestroy() Any method that doesn't work in the method is invalid .
Be careful : Use this method to hide the soft keyboard , It's best to make an empty judgment , Otherwise, null pointer exceptions may occur , For example, when there is no control to get focus in the current interface , be getCurrentFocus() This method yields a null.
The layout of soft keyboard , Sometimes the soft keyboard will overwrite some controls , At this time, how to jack up the whole interface , Let no control be overwritten ? There are two steps , First in activity Set a property in , as follows . The second step , Add one in the layout scrollview Put the view you want to be jacked up here , Then when the soft keyboard displays , Will be in scrollview Scroll inside to get space to display soft keyboard .

2
merge Label precautions
merge The label is only in the root layout FrameLayout Is useful when , Because the root layout of all Android interfaces is FrameLayout, So it can be used merge Label fusion .
merge After the label is used , Even if there is EditText Also can't get the focus automatically , Focus can only be set manually , call requestFocus() Method . Or with requestFocus stay XML In the layout file . After use, pay attention if it is in the root layout , You can't use LayoutInflater To generate a view, Otherwise, the following error will be reported , Because I am listview Of getview() I used this with merge Layout , So it collapsed . add ,inflater() Method can be set attach root by true Can be resolved , There will be no collapse .

Check the source code , It was in this place that an exception was thrown .

3
LinearLayout Be careful
The linear layout is horizontal by default , Make good use of it weight The attribute of weight . Very important point , If the direction is set to horizontal , be layout_gravity Of top And bottom Labels are ineffective . If the direction is set to vertical , be left And right It doesn't work , At this time, if you want to put it on the right , You can use space label , Set the width to 0dp, take layoutweight Set to 1 Just put it in front of the control .
4
Fragment( This is a big hole , Many people have met )
although Fragment It can make you app Enjoy the silky design , If your app Want to greatly improve the performance on the current basis , And the occupied memory is reduced , The same interface Activity Ratio of occupied memory Fragment More , Response speed Fragment Than Activty It's a lot faster in the middle and low-end mobile phones , It can even be several times ! If your app At present or in the future, there are platforms such as portable tablets , It can save you a lot of time and energy .
however Fragment Nested or single Activity+ many Fragment There are many pitfalls in architecture !!
In order to facilitate the introduction of later articles before this , Make a rule first “ The term ”, Android app There is a special case , Namely app When running in the background , When the system resources are tight, it will lead to app All of our resources are recycled ( Kill app The process of ), At this time, put app Back to the front desk from the background ,app Will restart . This situation is hereinafter referred to as :“ Memory restart ”.( Configuration changes such as screen rotation can also cause current Activity restart , Nature and “ Memory restart ” similar ).
In the system, we should put app Before recycling , The system will take Activity The state of is preserved ,Activity Of FragmentManager Responsible for the Activity Medium Fragment Save up . stay “ Memory restart ” after ,Activity Recovery from the top of the stack ,Fragment Will be in the host Activity Of onCreate Method call followed by recovery ( from onAttach Life cycle begins ).
problem 1、getActivity() Null pointer .
Maybe you've met getActivity() return null, Or run good code at ordinary times , stay “ Memory restart ” after , call getActivity() But back to null, Null pointer exception reported . Most of the reasons : You're calling getActivity() when , Current Fragment already onDetach() The host Activity. such as : you are here pop 了 Fragment after , The Fragment The asynchronous task of is still executing , And it was called after execution getActivity() Method , So it's going to be a null pointer .
terms of settlement :
more " Security " Methods :( about Fragment already onDetach This situation , We should avoid calling the host after that Activity object , For example, cancel these asynchronous tasks , But our team may be careless , So the scheme given below will ensure safety ).
stay Fragment Set a... In the base class Activity mActivity Global variable of , stay onAttach(Activity activity) Assignment in , Use mActivity Instead of getActivity(), Guarantee Fragment Even in onDetach after , Still holding Activity References to ( There is a risk of memory leaks , But if the asynchronous task doesn't stop , It may have leaked memory itself , comparison Crash, This kind of practice “ Security ” some ), namely :

problem 2、 abnormal :Can not perform this action after onSaveInstanceState.
There are a lot of little friends who encounter this exception , The reason for this exception is : Before you leave the present Activity Such cases , The system will call onSaveInstanceState() Save your current Activity The state of 、 Data etc. , Until we get back to that Activity Before (onResume() Before ), You execute Fragment Business , Will throw the exception !( It's usually something else Activity The callback of the current page to execute the transaction , Will cause the problem )
resolvent :
1、 The transaction uses commitAllowingStateLoss() Method submission , But it may cause the submission to be invalid !( host Activity When forced to kill ), about popBackStack() There is no counterpart popBackStackAllowingStateLoss() Method , So you can commit the transaction the next time it's visible .
2、 utilize onActivityForResult()/onNewIntent(), The integrity of transactions can be achieved , No loss of transactions .
A simple example code :

problem 3、Fragment Overlap exception —– How to use it correctly hide、show?
Generally meet the following 2 Conditions can overlap :
1、 Page restart occurred ( Rotate screen 、 Insufficient memory and other conditions are forcibly killed and restarted ).
2、 repeat replace|add Fragment perhaps Use show , hide control Fragment.
Why does it happen Fragment overlap ?
From the source point of view , Why does page restart cause overlap ?( In order to add Mode load Fragment When ).
We know Activity There was a onSaveInstanceState() Method , The method will be in Activity Will be kill When you call back ( For example, enter the backstage 、 Before the screen rotates 、 Jump to the next Activity In other cases, it will be called ). When Activity Only execute onPause When the method is used ( transparent Activity), At this time, if App Set up targetVersion Greater than 11 It won't be implemented onSaveInstanceState Method , At this time, the system helps us save a Bundle Data of type , We can meet our needs , Manually save some data such as playback progress , Then if a page restart occurs , We can do it in onRestoreInstanceState() or onCreate() in get This data , So as to restore the playback progress and other States , And produce Fragment The reason for overlap is related to the mechanism of saving state , The general reason is that before the page restarts , Saved it for us Fragment The state of , But when recovering after restart , The visible state of the view does not help us save , and Fragment The default is show state , That's why Fragment Overlap .
analysis :
We see first FragmentActivity Related source code :

You can see from the above source code ,FragmentActivity It really helped us save Fragment The state of , And it will help us recover after the page restarts ! Among them mFragments yes FragmentController, It's a Controller, Through internal FragmentHostCallback Indirect control FragmentManagerImpl, The relevant code is as follows :

As you can see from the code above FragmentController adopt FragmentHostCallback Inside FragmentManagerImpl Object to control the recovery work , Let's move on FragmentManagerImpl What did you do :

We go through saveAllState() See the key save code , It turned out to be through FragmentManagerState To preserve Fragment The state of 、 Where Fragment Stack subscript 、 Rollback stack status, etc . And in the restoreAllState() When you recover , adopt FragmentManagerState Inside FragmentState Of instantiate() Method restored Fragment( See the following analysis ), Let's take a look at FragmentManagerState:

We only see FragmentState, It also achieved Parcelable, Save the Fragment The name of the class 、 Subscript 、id、Tag、ContainerId as well as Arguments Data such as :

thus , We understand what the system saves for us Fragment In fact, in the end FragmentState In form , At this point, let's think about why it happens after the page restarts Fragment Overlap ? In fact, the answer is already obvious , According to the source code analysis above , We will find that FragmentState Not in it Hidden Status field ! and Hidden States correspond to Fragment Medium mHidden, This value defaults to false! I think you should understand , In order to add Mode load Fragment In the scene of , The system is recovering Fragment when ,mHidden=false, namely show state , So after the page restarts ,Activity Internal Fragment It's all about show Status display , And if you don't deal with it , Then it will happen Fragment Overlap !
Here's the solution : It's familiar to all of you findFragmentByTag:
That is to say add() perhaps replace() When binding a tag, Generally we use fragment The class name of tag, And then it's happening “ Memory restart ” when , adopt findFragmentByTag Find the corresponding Fragment, and hide() Need to be hidden fragment.
Here's a standard recovery :

If you want to recover to the one where the user left Fragment The interface of , You still need to be here onSaveInstanceState(Bundle outState) Keep the visible tag Subscript or subscript , stay onCreate“ Memory restart ” Block of code , Take out tag/ Subscript , Resume .
problem 4、Fragment The nested pits ?
In fact, a lot of nested pits encountered by some small partners , Most of this is due to the confusion over nested stack views , Just sort out the stack view relationship , Do a good job of recovery and the right choice is to use getFragmentManager() still getChildFragmentManager() We can avoid these problems .
stay support 23.2.0 In the following support library , For the insert Fragment Of startActivityForResult (), You will find that you can't be in onActivityResult() Received return value... In , Only the father at the top Fragment To receive , This is a support v4 One of the libraries. BUG, But in the support 23.2.0 In the library , The problem has been fixed , Nested children Fragment Can also receive the return data normally !
problem 5、 Unreliable stack method remove().
If you want someone to Fragment Out of the stack , Use remove() It's not reliable to join the fallback stack . If you are in the add At the same time Fragment Join the fallback stack :addToBackStack(name) Under the circumstances , It doesn't really mean Fragment Remove... From the stack , If you are in the 2 Seconds later ( Make sure Fragment The transaction has been completed ) Print getSupportFragmentManager().getFragments(), Will find that Fragment There is still a , And still can return to be remove Of Fragment, And it's a blank page . If you don't Fragment Join the fallback stack ,remove Method can be used to stack normally . If you join the fallback stack ,popBackStack() Series of methods can really stack .
problem 6、 Super deep pit Fragment Transition animation .
If you want to make the stack animation work normally , Need to use Fragment Of onCreateAnimation Control animation in , But there is also a cost , You need to solve a couple of holes in the stack animation .
1、pop Multiple Fragment Time transition animation The problems brought about by .
In the use of pop(tag/id) More than one stack Fragment In this case , Temporarily cancel the transition animation or delay the time of one animation to perform other transactions , The reason is that in this situation , May cause the stack to be out of order ( As mentioned above ), At the same time, if it happens “ Memory restart ” after , because Fragment When the transition animation is not finished, other methods can be performed , It can lead to Fragment State will not be FragmentManager Save normally .
2、 Enter the new Fragment And immediately close the current Fragment Some of the problems .
If you want from the present Fragment Into a new Fragment, And at the same time to close the current Fragment. Because the data structure is stack , So the right thing to do is first pop, Again add, But the transition animation will have the abnormal phenomenon of coverage , You need special treatment , Or it will flash !
Tip:
If you meet Fragment Of mNextAnim Null pointer exception ( Usually in your Fragment In case of being restarted ), So first you need to check if it works Fragment Is it null; Next is your Fragment When the transition animation is not over , Are you doing anything else ; The solution is to delay an animation time before executing a transaction , Or temporarily Fragment Set to no animation .
end
These are the pits I encountered , I hope you can actively add , Write good code together ~
quote :
1、https://blog.csdn.net/u012028250/article/details/120481898
2、https://blog.csdn.net/android_zhengyongbo/article/details/70676142
3、https://www.jianshu.com/p/b2a083e88925
4、https://blog.csdn.net/qq_21467035/article/details/115176508
from : In those years Android UI Various pits encountered in development
边栏推荐
- Tdengine helps Siemens' lightweight digital solutions
- Minitest -- applet automation testing framework
- Xcode编写SwiftUI代码时一个编译通过但导致预览(Preview)崩溃的小陷阱
- Cv:: mat conversion to qimage error
- Iterator iterator interface
- Bulk Rename Utility
- Log management platform of infrastructure and nail & email alarm notification
- Detailed explanation of common commands of vim (VIM use tutorial)
- Excel VBA 开发过程中遇到的一些问题,解决方案,持续更新
- C # 7 methods to obtain the current path
猜你喜欢
随机推荐
力扣解法汇总1331-数组序号转换
How does core data save data in SQLite
一些企业数据平台建设的思考
[Tanabata] Tanabata lonely little frog research edition? The final chapter of Tanabata Festival!
Swiftui 4.0's new navigation system
Why is it reverse to convert from other formats to BMP
复制excel行到指定行
Interviewer: what are the usage scenarios of ThreadLocal? How to avoid memory leakage?
SwiftUI 布局 —— 尺寸( 上 )
基于 MinIO 对象存储保障 Rancher 数据
SwiftUI 布局 —— 对齐
[ecmascript6] set and map
Log management platform of infrastructure and nail & email alarm notification
HCIP第十天
2022年安全员-A证操作证考试题库模拟考试平台操作
2022年熔化焊接与热切割考题及在线模拟考试
468 product planning and promotion plan (150 copies)
2022 safety officer-a certificate operation certificate examination question bank simulated examination platform operation
It's so hot that solar power can't take off? Hello, head
【七夕】七夕孤寡小青蛙究极版?七夕节最终章!



![[Tanabata] Tanabata lonely little frog research edition? The final chapter of Tanabata Festival!](/img/0b/4fc583a3dd4794b0c2b0d64d905be7.png)





