核桃干货 | Java后端线上问题排查常用命令收藏
有些布局的在很多页面都用到了,而且样式都一样,每次用到都要复制粘贴一大段,有没有办法可以复用呢? 解决了1中的问题之后,发现复用的布局外面总要额外套上一层布局,要知道布局嵌套是会影响性能的呐; 有些布局只有用到时才会显示,但是必须提前写好,虽然设置了为invisible或gone,还是多多少少会占用内存的。
1、include
layout:必填属性,为你需要插入当前主布局的布局名称,通过R.layout.xx的方式引用; id:当你想给通过include添加进来的布局设置一个id的时候就可以使用这个属性,它可以重写插入主布局的布局id。
1.1 常规使用
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:gravity="center_vertical"
android:textSize="14sp"
android:background="@android:color/holo_red_light"
android:layout_height="40dp">
</TextView>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".ViewOptimizationActivity">
<!--include标签的使用-->
<TextView
android:textSize="18sp"
android:text="1、include标签的使用"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<include
android:id="@+id/tv_include1"
layout="@layout/layout_include"/>
</LinearLayout>
TextView tvInclude1 = findViewById(R.id.tv_include1);
tvInclude1.setText("1.1 常规下的include布局");
1.2 重写根布局的布局属性
<include
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_marginEnd="40dp"
android:id="@+id/tv_include2"
layout="@layout/layout_include"/>
1.3 控件ID相同时的处理
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:background="@android:color/holo_orange_light"
android:layout_height="wrap_content">
<TextView
android:gravity="center_vertical"
android:id="@+id/tv_same"
android:layout_width="match_parent"
android:layout_height="50dp" />
</FrameLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".ViewOptimizationActivity">
<!--include标签的使用-->
……
<include layout="@layout/layout_include2"/>
<include
android:id="@+id/view_same"
layout="@layout/layout_include2"/>
</LinearLayout>
TextView tvSame = findViewById(R.id.tv_same);
tvSame.setText("1.3 这里的TextView的ID是tv_same");
FrameLayout viewSame = findViewById(R.id.view_same);
TextView tvSame2 = viewSame.findViewById(R.id.tv_same);
tvSame2.setText("1.3 这里的TextView的ID也是tv_same");
2、merge
2.1 merge常规使用
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tv_merge1"
android:text="我是merge中的TextView1"
android:background="@android:color/holo_green_light"
android:gravity="center"
android:layout_width="wrap_content"
android:layout_height="40dp" />
<TextView
android:layout_toEndOf="@+id/tv_merge1"
android:id="@+id/tv_merge2"
android:text="我是merge中的TextView2"
android:background="@android:color/holo_blue_light"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="40dp" />
</merge>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<include
android:id="@+id/view_merge"
layout="@layout/layout_merge"/>
</RelativeLayout>
2.3 merge的ID
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<include
android:id="@+id/view_merge"
layout="@layout/layout_merge"/>
<TextView
android:text="我不是merge中的布局"
android:layout_below="@+id/view_merge"
android:background="@android:color/holo_purple"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="40dp"/>
</RelativeLayout>
3、ViewStub
android:layout:ViewStub需要填充的视图名称,为“R.layout.xx”的形式; android:inflateId:重写被填充的视图的父布局id。
3.1 填充布局的正确方式
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:background="@android:color/holo_blue_dark"
android:layout_height="100dp">
<Switch
android:id="@+id/sw"
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</FrameLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".ViewOptimizationActivity">
<!--ViewStub标签的使用-->
<TextView
android:textSize="18sp"
android:text="3、ViewStub标签的使用"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ViewStub
android:id="@+id/view_stub"
android:inflatedId="@+id/view_inflate"
android:layout="@layout/layout_view_stub"
android:layout_width="match_parent"
android:layout_height="100dp" />
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:text="显示"
android:id="@+id/btn_show"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content" />
<Button
android:text="隐藏"
android:id="@+id/btn_hide"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content" />
<Button
android:text="操作父布局控件"
android:id="@+id/btn_control"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
viewStub.setOnInflateListener(new ViewStub.OnInflateListener() {
@Override
public void onInflate(ViewStub viewStub, View view) {
Toast.makeText(ViewOptimizationActivity.this, "ViewStub加载了", Toast.LENGTH_SHORT).show();
}
});
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.btn_show:
viewStub.inflate();
break;
case R.id.btn_hide:
viewStub.setVisibility(View.GONE);
break;
default:
break;
}
}
java.lang.IllegalStateException: ViewStub must have a non-null ViewGroup viewParent
public View inflate() {
final ViewParent viewParent = getParent();
if (viewParent != null && viewParent instanceof ViewGroup) {
if (mLayoutResource != 0) {
final ViewGroup parent = (ViewGroup) viewParent;
final View view = inflateViewNoAdd(parent);
replaceSelfWithView(view, parent);
mInflatedViewRef = new WeakReference<>(view);
if (mInflateListener != null) {
mInflateListener.onInflate(this, view);
}
return view;
} else {
throw new IllegalArgumentException("ViewStub must have a valid layoutResource");
}
} else {
throw new IllegalStateException("ViewStub must have a non-null ViewGroup viewParent");
}
}
private void replaceSelfWithView(View view, ViewGroup parent) {
final int index = parent.indexOfChild(this);
parent.removeViewInLayout(this);
final ViewGroup.LayoutParams layoutParams = getLayoutParams();
if (layoutParams != null) {
parent.addView(view, index, layoutParams);
} else {
parent.addView(view, index);
}
}
3.1.1 捕获异常
try {
viewStub.inflate();
} catch (IllegalStateException e) {
Log.e("Tag",e.toString());
view.setVisibility(View.VISIBLE);
}
3.1.2 通过监听ViewStub的填充事件
if (isViewStubShow){
viewStub.setVisibility(View.VISIBLE);
}else {
viewStub.inflate();
}
3.1.3 直接调用setVisibility()方法
public void setVisibility(int visibility) {
if (mInflatedViewRef != null) {
View view = mInflatedViewRef.get();
if (view != null) {
view.setVisibility(visibility);
} else {
throw new IllegalStateException("setVisibility called on un-referenced view");
}
} else {
super.setVisibility(visibility);
if (visibility == VISIBLE || visibility == INVISIBLE) {
inflate();
}
}
}
3.2 viewStub.getVisibility()为何总是等于0?
if (viewStub.getVisibility() == View.GONE){
viewStub.setVisibility(View.VISIBLE);
}else {
viewStub.setVisibility(View.GONE);
}
3.3 操作布局控件
//1、初始化被inflate的布局后再初始化其中的控件,
FrameLayout frameLayout = findViewById(R.id.view_inflate);//android:inflatedId设置的id
Switch sw = frameLayout.findViewById(R.id.sw);
sw.toggle();
//2、直接初始化控件
Switch sw = findViewById(R.id.sw);
sw.toggle();