Solution 1: Use components provided by the Android library for layout optimization
1. Use the <include/> tag to reuse our layout
The layout attribute is used to introduce the layout file we want to use. The advantage is that the layout can be reused.
<include
android:id="@+id/layoutId"
layout="@layout/layout"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
If we set the id attribute for the root container of the layout loaded by include, and also set the id attribute in the include tag, and when we need to obtain the control object of the root container in the code, we must set the two ids to the same name! Otherwise, the root container object will not be obtained, which is null , which means that the layout loaded by our instantiated include is null .
2. Use the <ViewStub/> tag for lazy loading
We often encounter situations where runtime dynamically decides which View or layout to display based on conditions. A common approach is to write all Views on it, first set their visibility to View.GONE , and then dynamically change its visibility in the code. The advantage of this approach is that the logic is simple and the control is flexible. But its disadvantage is that it consumes resources. Although the View 's initial visibility is View.GONE , the View will still be Inflate during Inflate layout , which means that objects will still be created, instantiated, and properties will be set. In other words, resources such as memory will be consumed.
<ViewStub/ > is a lightweight View . It is invisible and does not occupy the layout position by default. During Inflate layout, only ViewStub will be initialized. Call the original properties of ViewStub when it is to be displayed.
viewStub.setVisibility(View.VISIBLE);//显示
viewStub.inflate();//显示
3. Use the <Merge/> tag to reduce the layout level
Merge is mainly used to optimize the UI layout and delete redundant levels. <merge/> is mostly used to replace FrameLayout or when one layout contains another layout. The <merge/> tag is used to eliminate redundant views in the master-disciple hierarchy. Group. For example, if your Zhu layout file is vertical, if you introduce a vertical layout <include> . At this time, if the include layout uses LinearLayout , it will be meaningless, and it will slow down your UI performance. At this time, you can use the <merge/> tag optimization. The <merge> tag is to exclude the redundant viewgroup generated by inserting one layout into another layout. When the layout root layout has no actual attributes and only serves as a simple parent viewgroup (such as our LinerLayout, etc.) , you can use merge instead . , merge will not be drawn as a hierarchy, <merge /> can only be used as the root tag of XML layout. When Inflate a layout file starting with <merge /> , a parent must be specifiedViewGroup , and attachToRoot must be set to true , (attachToRoot: whether to attach root to the root view of the layout file). Its <merge /> size is determined by its sub- View .
Solution 2: Use strong and weak to control memory
Characteristics of strong references: When memory is insufficient, jvm starts garbage collection. For strongly referenced objects, even if an OOM exception occurs, the object will not be recycled. Most Android memory leaks are caused by strong references, which are referenced through the new keyword. of.
Features of soft reference: Soft reference is a reference with relatively strong reference weakness. It needs to be implemented using the SoftReference class. When the system memory is sufficient, it will not be recycled. When the system memory is insufficient, it will be recycled. Soft references are usually used in Use it when the memory is relatively sensitive, and you can also use soft applications to solve our memory leak problem.
Characteristics of weak references: Weak references needto be implemented using WeakReference , which has a shorter lifetime than soft references. Regardless of whether the memory is sufficient, it will be recycled as long as gc scans it.
Features of virtual reference: Virtual reference is implemented using the PhantomReference class. I have never used it after so many years of development. I don’t know where its usage scenarios are. If an object only holds a virtual reference, then it is the same as not having any reference. It may be garbage collected at any time. It cannot be used alone or access objects through it. Virtual references must be used together with ReferenceQueue . The main function of virtual references is to track the status of objects being garbage collected.
ReferenceQueue : The function of this class is that the object will be stored in the reference queue after being garbage collected.
Option 3: Percentage adaptation to the screen
Adaptation plan one:
The idea of this plan is written according to my own understanding. Although it is 100% adaptable, there may be some small details that I have not thought of. I will give a simple example for reference only!
First of all, the technologies to be used are as follows:
One is that we need annotations
As for the knowledge points here in annotations, there are original annotations and custom annotations, so our annotations are all annotations written based on the original annotations.
Mainly explain two commonly used annotations, the code is as follows:
//使用两个原注解
@Retention(RetentionPolicy.RUNTIME) // 什么时候运行呢?RUNTIME这个字段就是运行时加载 节省资源
@Target(ElementType.FIELD)//作用到哪里?FIELD这个字段就是作用到我们的字段上
public @interface AutoSize {
//接收的参数 可以接收 int String Class
int id();//接收组件id
int width();//接收宽的比例
int hight();//接收高的比例
}
The second is our reflection technology
With the parameters that the annotations help us receive, we can do some operations we want before running, but how can we achieve the functions we want with these parameters of Class String int? Then we need technical reflection at this time. code show as below:
public class MainActivity extends AppCompatActivity {
@AutoSize(width = 2,hight = 2,id=R.id.btn_one)//传入比例
Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AutoUtils.bind(this,R.layout.activity_main3);
}
}
/**
* 按比例对我们的View进行缩放
*/
public class AutoUtils {
private static int mLayoutId;
public static void bind(Activity activity,int layoutId){
activity.setContentView(layoutId);
//通过本类的Activity获得Activity视图中的子View这样我们就可以控制他的宽高了
bindView(activity);
}
private static void bindView(Activity activity){
Class<? extends Activity> aClass = activity.getClass();
Field[] declaredFields = aClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
//如果我们的字段有注解那么就返回,没有的话就返回null,就是判断有没有注解
AutoSize annotation = declaredField.getAnnotation(AutoSize.class);
if (annotation!=null){
//获得屏幕的宽高
Display defaultDisplay = activity.getWindow().getWindowManager().getDefaultDisplay();
int width = defaultDisplay.getWidth();
int height = defaultDisplay.getHeight()-getStatusBarHeight(activity);
Log.d("msg","状态栏高度"+getStatusBarHeight(activity));
//annotation是我们的注解,可以拿到我们通过注解传进来的值
LinearLayout.LayoutParams params=new LinearLayout.LayoutParams(
width/annotation.width(),height/annotation.hight());
View mView = activity.findViewById(annotation.id());//通过传进来的activity调用查找我们的View
mView.setLayoutParams(params);
}
}
}
/**
* 获取状态栏高度
* @param context
* @return
*/
public static int getStatusBarHeight(Context context) {
Resources resources = context.getResources();
int resourceId = resources.getIdentifier("status_bar_height", "dimen", "android");
int height = resources.getDimensionPixelSize(resourceId);
return height;
}
Before scaling, that is, when our width and height are both wrap_content
缩放后,代码是按照屏幕二分之一的比例改变的View大小