1024工场

新技术,新未来,尽在1024工场...

Android总结:命名空间
在使用lint工具进行代码检测的时候,有一个XML类型的报错如下:Namespace declaration is never used(错误代码如下图)。

脑海里突然浮现起一个名词—命名空间,由于一直以来对这个知识点理解不是很透彻,查阅相关资料并学习总结如下;

一、命名空间简介
1.命名空间作用
作用:
提供避免元素命名冲突的方法,里面存放的是特性属性的集合;
例如:Android的View存在id属性—代表View的唯一id,而你自定义的View也想自定义一个id属性—代表该类型View编号。那么这个时候命名空间就派上用场了,你可能会分别生成android:id和myview:id代表两个属性(android和myview即命名空间的名称);
2.命名空间分类
在Android中的命名空间可分为3种,如下:
  android命名空间:xmlns:android="http://schemas.android.com/apk/res/android;
  tools命名空间:xmlns:tools="http://schemas.android.com/tools;
  自定义命名空间:xmlns:app="http://schemas.android.com/apk/res-auto"

二、命名空间实践
2.1 android命名空间

android命名空间包含了系统提供了很多属性。在Android布局文件中,必须在根元素上定义这个命名空间;
xmlns:android="http://schemas.android.com/apk/res/android" ,如下:
<RelativeLayout xmlns:qproject="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    qproject:id="@+id/activity_name_space"
    qproject:layout_width="match_parent"
    qproject:layout_height="match_parent"
    ... ...
    tools:context="com.qproject.knowledge.NameSpaceActivity">
    <TextView
        qproject:layout_width="wrap_content"
        qproject:layout_height="wrap_content"
        qproject:text="namespace" />
</RelativeLayout>
  xmlns:声明我们要开始定义一个命名空间;
  qproject:namespace-prefix,实际就是命名空间的名字;
  http://schemas.android.com/apk/res/android:一个URI(统一资源标示符),值固定不变,相当于一个常量;
大家应该注意到了,布局中命名空间名字我们使用qproject:替代了android:,以qpoject:开头的属性便是引用了命名空间http://schemas.android.com/apk/res/android中的属性, 这样也可以正常编译运行;
2.2 tools命名空间
2.2.1 tools命名空间简介

Android Studio在tools命名空间支持各种属性,来实现设计时功能(如在你的布局中显示哪个fragment)或者编译时行为(如给你的XML资源使用哪种压缩模式 )。当你构建你的app的时候,构建工具会移除这些属性,所以对于你的APK的大小和运行时行为没有影响。
为了使用这些属性,在你想使用它们的每个XML文件的根元素添加tools命名空间—xmlns:tools="http://schemas.android.com/tool",如下所示:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    ... ... 
    tools:context="com.qproject.knowledge.NameSpaceActivity">
    <TextView ... ... />
</RelativeLayout>
2.2.2 tools命名空间实践
tools:ignore

该属性为错误处理属性,告知Lint工具忽略相关类型ID错误的检测;
1.查看鼠标悬停在lint检测错误处,弹框提示错误如下:

2.Alt+Enter(Eclipse快捷键)提示处理选择,使用tools:ignore="ContentDescription"提示lint忽略该问题;

3.添加后无lint错误提示;

注意:在某些错误警告,Alt+Enter无处理选择提示,需要手动输入tools:ingore="xxx"。如果不知道相关问题ID,在Android Studio->Analyze->Inspect Code->选择你想检查的目录+检查配置->点击OK按钮。执行检查后,在Inspection窗口右侧选在相关错误,左侧即提示该错误类型的ID;

tools:intead of android:
该属性为设计时视图属性,向布局预览器中插入样本数据,在运行时无效果;
1.在TextView视图中除android:text之外添加tools:text属性,在布局预览器观察生效text为tools:text="TextView2";

2.构建运行应用,观察在运行时生效文案为android:text="TextView1";

tools:shrinkMode
该属性为资源压缩属性,指定构建工具执行资源压缩时使用的模式;
1.knowledge模块src/res/drawable目录下存在两个位图文件dyused_knowledge_img.png和unused_knowledge_img.png,在NameSpaceActivity.java中动态引用dyused_knowledge_img.png位图;
knowledge/src/main/java/com/qproject/knowledge/NameSpaceActivity.java文件
public class NameSpaceActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_namespace);
        //动态引用dyused_knowledge_img图片,在safe模式下保留
        int res = getResources().getIdentifier("dyused_knowledge_img", "drawable", getPackageName());
    }
}
2.主项目main的构建文件main/build.gradle配置资源压缩(在knowledge配置不生效),;
main/build.gradle文件
apply plugin: 'com.android.application'
android {
    ... ...
    buildTypes {
        release {
            //启动资源压缩
            shrinkResources true
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    ... ...
}
3.knowledge模块src/main/res/raw/keep.xml配置压缩模式为safe模式下进行构建打包,动态引用图片dyused_knowledge_img.png被保留,未引用图片unused_knowledge_img.png被处理;
knowledge/src/main/res/raw/keep.xml文件
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"
    tools:shrinkMode="safe"/>

4.在shrinkMode为strict模式下进行构建打包,动态引用图片dyused_knowledge_img.png被处理,未引用图片unused_knowledge_img.png被处理;
knowledge/src/main/res/raw/keep.xml文件
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"
    tools:shrinkMode="strict"/>

2.3 自定义命名空间
2.3.1 自定义命名空间简介

自定义命名空间通常用在自定义控件中,用来提供自定义控件的自定义属性;
2.3.2自定义命名空间实践
下面我们通过一个简单的自定义控件CutomView来实践自定义命名空间的使用,项目目录如下:

1.创建CustomView,实现onDraw绘制一个圆形,并提供自定义属性fillColor来设置填充颜色;
com/qproject/knowledge/view/CustomView.java文件
public class CustomView extends View {
    private int fillColor = Color.BLACK;
    private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
    public CustomView(Context context) {
        super(context);
        init();
    }
    public CustomView(Context context, AttributeSet attrs) {
        super(context, attrs);
        //获取自定义属性
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CustomView);
        fillColor = typedArray.getColor(R.styleable.CustomView_fillColor, Color.BLACK);
        typedArray.recycle();
        init();
    }
    private void init() {
        //设置画笔的颜色
        paint.setColor(fillColor);
    }
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawCircle(50, 50, 30, paint);
    }
}
com/qproject/knowledge/res/value/attrs.xml文件
<?xml version="1.0" encoding="utf-8"?>
<resources>
     //设置自定义属性fillColor
    <declare-styleable name="CustomView">
        <attr name="fillColor" format="color" />
    </declare-styleable>
</resources>
2.在NameSpaceActivity布局中使用CustomView,使用自定义命名空间,通过fillColor属性指定颜色进行绘制;
com/qproject/knowledge/res/layout/activity_namespace.xml文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    //使用自定义命名空间,名称为app
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/activity_namespace"
    ... ...
    tools:context="com.qproject.knowledge.NameSpaceActivity">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="namespace"/>
    ... ...
    //使用CustomView,使用app:fillColor设置填充色
    <com.qproject.knowledge.view.CustomView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:fillColor="#00acef"/>
</LinearLayout>
3.运行结果:


三、tools命名空间总结
错误处理属性:下面的属性帮助抑制lint警告信息;
属性
用于
使用
作用
示例
tools:ignore任何元素Lint接受一个用逗号分隔的列表,指定Lint在这个元素或者任何它的子元素检测忽略的问题ID;<string name="show_all_apps" tools:ignore="MissingTranslation">All</string>
tools:targetApi任何元素Lint
这个属性的功能和Java代码中的@TargetApi注解相同:指定这个元素支持的API级别(无论是一个整数还是一个代码名称);
这告诉Lint你相信这个元素(和任何子元素)将仅用于指定API或者更高级别。如果元素或者它的属性在你使用minSdkVersion指定的API级别上不可用,会阻止Lint警告你;
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" tools:targetApi="14">
tools:locale<resources>Lint,Android Studio editor告诉Lint在你给定的<resource>元素(因为Lint默认是英语)中默认的语言/区域是什么,为了避免拼写检查警告。这个值必须是一个有效的区域限定符;<resources xmlns:tools="http://schemas.android.com/tools" tools:locale="es">
设计时视图属性:下面的属性定义的布局特性,仅仅在Android Studio布局预览中可见;
属性
用于
使用
作用
示例
tools:intead of android:<view>Android Studio 布局编辑器
通过在一些Android framework的<view>属性使用tools:前缀替代android:,在你的布局预览中插入样本数据。该数据在运行时都不会被使用,当你想在布局预览中事先查看效果时非常有用;
例如,如果android:text属性值在运行被设置,或者你想查看到与默认值不同的布局,你可以添加tools:text来为布局预览指定一些文案;
tools:context任何根<view>Lint,Android布局编辑器声明这个布局默认和哪个Activity相关联。它启动了在编辑器或者布局预览中需要这个Activity上下文的功能,例如什么布局主题应该被预览,和当你从快速修复选择往哪个Activity中插入onClick处理;
tools:layout<fragment>Android Studio布局编辑器声明了你想在布局预览中这个fragment(因为布局预览不能执行设置布局的相关代码代码)里面绘制哪个布局;<fragment android:name="com.example.master.ItemListFragment" tools:layout="@layout/list_content" />
tools:listitem/tools:listheader/tools:listfotter<AdapterView>(和如<ListView>的子类)Android Studio布局编辑器指定什么布局显示在列表的列表项,头部和底部。在布局中的任何数据字段都会被数字内容填充,如“Item 1”,使得列表不重复;
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@android:id/list"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:listitem="@layout/sample_list_item"
    tools:listheader="@layout/sample_list_header"
    tools:listitem="@layout/sample_list_footer" />
tools/showIn任何被<include>引用的根<view>Android Studio布局编辑器指定一个布局,你可以把它当做include使用,因为当它被嵌入到父布局中时出现了,所以你能预览(和编辑)这个文件 ;
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:text="@string/hello_world"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    tools:showIn="@layout/activity_main" />
tools/menu任何根<view>Android 布局编辑器指定了在布局预览中app bar应该显示那个菜单。这个值可以是一个或者多个菜单id,通过逗号分隔(不使用@menu/或者)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:menu="menu1,menu2" />
资源压缩属性:下面属性允许你在使用资源压缩的时候,启动严格引用检查,并且声明是否保留或删除某个资源;
属性
用于
使用
作用
示例
tools:shrinkMode<resources>执行资源压缩的构建工具
指定构建工具是否使用“安全模式”(保留直接被引用或者通过调用Resource.getIndentifier()等动态被引用的所有资源)或者“严格模式”(仅仅保留直接在代码中或者在其它资源中被引用的资源),默认是使用安全模式;
当你启动严格模式,你可能需要使用tools:keep来声明实际你想保留的资源,并且使用tools:discard来明确你要删除的资源;
<resources xmlns:tools="http://schemas.android.com/tools" tools:shrinkMode="strict" />
tools:keep<resources>执行资源压缩的构建工具
当使用资源压缩来删除没有被使用的资源,让你指定要保留的资源(通常是因为它们在运行时以间接的方式被引用,例如通过传递一个动态生成的资源名称给Resources.getIndentifier()方法);
在你的资源目录创建一个XML文件(例如,在res/raw/keep.xml)包含一个<resources>标识,并在tools:keep属性中以逗号分隔列表指定保留的每个资源。

<resources xmlns:tools="http://schemas.android.com/tools" tools:keep="@layout/used_1,@layout/used_2,@layout/*_3" />
tools:discard<resources>执行资源压缩的构建工具
当你使用资源压缩来删除没有使用的资源的时候,它允许你指定你明确想删除(通常是因为资源被引用,但是不影响你的app的方式,或者因为Gradle插件错误判断资源被引用了)的资源;
在你的资源目录创建一个XML文件(例如,在res/raw/keep.xml)包含<resources>标识,并且在tools:discard属性中以逗号分隔列表指定要删除的每个资源;
<resources xmlns:tools="http://schemas.android.com/tools" tools:discard="@layout/unused_1" />

四、代码库

QProject:https://github.com/Pengchengxiang/QProject  分支:knowledge/namespace

新技术,新未来!欢迎大家关注“1024工场”微信服务号,时刻关注我们的最新的技术讯息!(甭客气!尽情的扫描或者长按!)

阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/p106786860/article/details/53943540
个人分类: Android总结
想对作者说点什么? 我来说一句