发现安卓里一个牛逼的开发工具ViewDebug.ExportedProperty

81 篇文章 3 订阅

转载自:原地址

使用@ViewDebug.ExportedProperty注解,我们可以在android提供的工具Monitor(或已经废弃的DDMS)中的Hierarchy Viewer中调试View的属性。我们可以直接观察View的某个变量或方法的值,实时观察View的状态变化。


#ExprotedProperty注解源码

/**
 * This annotation can be used to mark fields and methods to be dumped by
 * the view server. Only non-void methods with no arguments can be annotated
 * by this annotation.
 */
@Target({ ElementType.FIELD, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface ExportedProperty {
    /**
     * When resolveId is true, and if the annotated field/method return value
     * is an int, the value is converted to an Android's resource name.
     *
     * @return true if the property's value must be transformed into an Android
     *         resource name, false otherwise
     */
    boolean resolveId() default false;
    /**
     * A mapping can be defined to map int values to specific strings. For
     * instance, View.getVisibility() returns 0, 4 or 8. However, these values
     * actually mean VISIBLE, INVISIBLE and GONE. A mapping can be used to see
     * these human readable values:
     *
     * <pre>
     * @ViewDebug.ExportedProperty(mapping = {
     *     @ViewDebug.IntToString(from = 0, to = "VISIBLE"),
     *     @ViewDebug.IntToString(from = 4, to = "INVISIBLE"),
     *     @ViewDebug.IntToString(from = 8, to = "GONE")
     * })
     * public int getVisibility() { ...
     * <pre>
     *
     * @return An array of int to String mappings
     *
     * @see android.view.ViewDebug.IntToString
     */
    IntToString[] mapping() default { };
    /**
     * A mapping can be defined to map array indices to specific strings.
     * A mapping can be used to see human readable values for the indices
     * of an array:
     *
     * <pre>
     * @ViewDebug.ExportedProperty(indexMapping = {
     *     @ViewDebug.IntToString(from = 0, to = "INVALID"),
     *     @ViewDebug.IntToString(from = 1, to = "FIRST"),
     *     @ViewDebug.IntToString(from = 2, to = "SECOND")
     * })
     * private int[] mElements;
     * <pre>
     *
     * @return An array of int to String mappings
     *
     * @see android.view.ViewDebug.IntToString
     * @see #mapping()
     */
    IntToString[] indexMapping() default { };
    /**
     * A flags mapping can be defined to map flags encoded in an integer to
     * specific strings. A mapping can be used to see human readable values
     * for the flags of an integer:
     *
     * <pre>
     * @ViewDebug.ExportedProperty(flagMapping = {
     *     @ViewDebug.FlagToString(mask = ENABLED_MASK, equals = ENABLED, name = "ENABLED"),
     *     @ViewDebug.FlagToString(mask = ENABLED_MASK, equals = DISABLED, name = "DISABLED"),
     * })
     * private int mFlags;
     * <pre>
     *
     * A specified String is output when the following is true:
     *
     * @return An array of int to String mappings
     */
    FlagToString[] flagMapping() default { };
    /**
     * When deep export is turned on, this property is not dumped. Instead, the
     * properties contained in this property are dumped. Each child property
     * is prefixed with the name of this property.
     *
     * @return true if the properties of this property should be dumped
     *
     * @see #prefix()
     */
    boolean deepExport() default false;
    /**
     * The prefix to use on child properties when deep export is enabled
     *
     * @return a prefix as a String
     *
     * @see #deepExport()
     */
    String prefix() default "";
    /**
     * Specifies the category the property falls into, such as measurement,
     * layout, drawing, etc.
     *
     * @return the category as String
     */
    String category() default "";
}

#使用

下面是@ViewDebug.ExportedProperty注解的部分属性的使用介绍:

##1.category

category用来指定属性的类别,例如measurement, layout, drawing等。我们在自定义View中为使用@ViewDebug.ExportedProperty注解的变量或方法指定category:

@ExportedProperty(category = "marquee")
int x = 1;

@Override
@ExportedProperty(category = "marquee")
public boolean isFocused() {
    return true;
}

运行程序,在Hierarchy Viewer中查看View的属性如下:

##2.resolveId

当resolveId为true时,如果使用注解的变量或方法的值为int数据,那么这个值会被转化为对应的Android资源的名称。

在R.java中找到一个资源ID:

public static final int activity_main=0x7f030000;

使用注解属性resolveId:

@ExportedProperty(category = "marquee", resolveId = true)
int b = 0x7f030000;

结果如下:

##3.mapping

mapping可以将int值映射到指定的字符串值,例如View.getVisibility()返回的值是int值,View中使用注解将其映射为字符串,其中0为”VISIBLE”,4为”INVISIBLE”,8为”GONE”。我们重载View.getVisibility()并加上我们自己定制的映射:

@Override
@ViewDebug.ExportedProperty(category = "marquee",
        mapping = {
                @ViewDebug.IntToString(from = VISIBLE, to = "MARQUEE_VISIBLE"),
                @ViewDebug.IntToString(from = INVISIBLE, to = "MARQUEE_INVISIBLE"),
                @ViewDebug.IntToString(from = GONE, to = "MARQUEE_GONE")
        })
public int getVisibility() {
    return super.getVisibility();
}

结果如下:

##4.indexMapping

indexMapping可以将数组的序号映射为字符串。

@ExportedProperty(category = "marquee",
        indexMapping = {
                @ViewDebug.IntToString(from = 0, to = "MARQUEE_FIRST"),
                @ViewDebug.IntToString(from = 1, to = "MARQUEE_SECOND"),
                @ViewDebug.IntToString(from = 2, to = "MARQUEE_THIRD")
        })
int[] elements = new int[] {
        111, 222, 333
};

结果如下:


#Demo

package com.daemon.demo;

import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.ViewDebug;
import android.view.ViewDebug.ExportedProperty;
import android.widget.TextView;

public class MarqueeText extends TextView {

    public MarqueeText(Context context) {
        super(context);
    }

    public MarqueeText(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MarqueeText(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
    }

    @ExportedProperty(category = "marquee")
    int x = 1;

    @Override
    @ExportedProperty(category = "marquee")
    public boolean isFocused() {
        return true;
    }

    @ExportedProperty(category = "marquee", resolveId = true)
    int b = 0x7f030000;

    @Override
    @ViewDebug.ExportedProperty(category = "marquee",
            mapping = {
                    @ViewDebug.IntToString(from = VISIBLE, to = "MARQUEE_VISIBLE"),
                    @ViewDebug.IntToString(from = INVISIBLE, to = "MARQUEE_INVISIBLE"),
                    @ViewDebug.IntToString(from = GONE, to = "MARQUEE_GONE")
            })
    public int getVisibility() {
        return super.getVisibility();
    }

    @ExportedProperty(category = "marquee",
            indexMapping = {
                    @ViewDebug.IntToString(from = 0, to = "MARQUEE_FIRST"),
                    @ViewDebug.IntToString(from = 1, to = "MARQUEE_SECOND"),
                    @ViewDebug.IntToString(from = 2, to = "MARQUEE_THIRD")
            })
    int[] elements = new int[] {
            111, 222, 333
    };
}

#参考

@ViewDebug.ExportedProperty

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
开发工具在软件开发生命周期中扮演着至关重要的角色,它们旨在简化和加速从概念设计到产品部署的各个环节。以下是开发工具的主要作用: 代码编写与编辑: 提供集成开发环境(IDE),如Visual Studio、Eclipse、Android Studio和Sublime Text等,这些工具集成了文本编辑器,支持语法高亮、自动补全、代码片段管理和版本控制等功能,有助于开发者高效编写和维护代码。 项目管理: 支持项目创建、组织、构建自动化以及依赖管理,确保不同模块和组件之间的协调一致。 编译与构建: 包括编译器、构建工具(如Make、Gradle、Maven)等,用于将源代码转换为可执行文件或库,并进行资源打包、优化等处理。 调试与测试: 集成调试器允许开发者逐行执行代码,设置断点、查看变量值、跟踪调用堆栈等,帮助定位并修复代码中的错误。 测试框架和工具则协助开发者编写和运行单元测试、集成测试及性能测试,确保软件质量。 版本控制与协作: 通过集成Git、SVN等版本控制系统,支持团队成员间的代码共享、分支管理、合并请求和冲突解决。 可视化设计与原型制作: 对于UI/UX设计,有界面设计工具,如Sketch、Adobe XD,可以帮助设计师快速构建应用程序界面模型,并生成规范的设计稿供开发人员参考实现。 跨平台支持: 跨平台开发工具如Xamarin、React Native和Flutter,让开发者使用一种语言或框架编写可以在多个操作系统上运行的应用程序。 文档编写与API管理: 文档生成工具可以自动生成代码注释文档,便于团队内外理解和使用项目代码。 API管理工具则方便开发者创建、测试、发布和维护API接口。 持续集成与持续部署(CI/CD): Jenkins、Travis CI、GitHub Actions等工具负责自动化构建、测试和部署流程,提高交付效率和可靠性。 数据库管理与ORM工具: 数据库客户端工具用于连接、查询、更新数据库,ORM(对象关系映射)工具简化了数据操作和持久化层的开发工作。 总之,开发工具极大地提升了软件工程师的工作效率,保证了开发过程中的准确性与一致性,同时也促进了团队合作,使得软件开发更系统化、规范化和工业化。
Chatgpt学习资料项目资料 用于实战ChatgptAI技术 源代码 供参考(代码+使用说明) Chatgpt学习资料项目资料 用于实战ChatgptAI技术 源代码 供参考(代码+使用说明) Chatgpt学习资料项目资料 用于实战ChatgptAI技术 源代码 供参考(代码+使用说明) Chatgpt学习资料项目资料 用于实战ChatgptAI技术 源代码 供参考(代码+使用说明) Chatgpt学习资料项目资料 用于实战ChatgptAI技术 源代码 供参考(代码+使用说明) Chatgpt学习资料项目资料 用于实战ChatgptAI技术 源代码 供参考(代码+使用说明) Chatgpt学习资料项目资料 用于实战ChatgptAI技术 源代码 供参考(代码+使用说明) Chatgpt学习资料项目资料 用于实战ChatgptAI技术 源代码 供参考(代码+使用说明) Chatgpt学习资料项目资料 用于实战ChatgptAI技术 源代码 供参考(代码+使用说明) Chatgpt学习资料项目资料 用于实战ChatgptAI技术 源代码 供参考(代码+使用说明) Chatgpt学习资料项目资料 用于实战ChatgptAI技术 源代码 供参考(代码+使用说明) Chatgpt学习资料项目资料 用于实战ChatgptAI技术 源代码 供参考(代码+使用说明) Chatgpt学习资料项目资料 用于实战ChatgptAI技术 源代码 供参考(代码+使用说明) Chatgpt学习资料项目资料 用于实战ChatgptAI技术 源代码 供参考(代码+使用说明) Chatgpt学习资料项目资料 用于实战ChatgptAI技术 源代码 供参考(代码+使用说明) Chatgpt学习资料项目资料 用于实战ChatgptAI技术 源代码 供参考(代码+使用说明) Chatgpt学习资料项目资料 用于实战ChatgptAI技术 源代码 供参考(代码+使用说明) Chatgpt学习资料项目资料 用于实战ChatgptAI技术 源代码 供参考(代码+使用说明) Chatgpt学习资料项目资料 用于实战ChatgptAI技术 源代码 供参考(代码+使用说明) Chatgpt学习资料项目资料 用于实战ChatgptAI技术 源代码 供参考(代码+使用说明) Chatgpt学习资料项目资料 用于实战ChatgptAI技术 源代码 供参考(代码+使用说明) Chatgpt学习资料项目资料 用于实战ChatgptAI技术 源代码 供参考(代码+使用说明) Chatgpt学习资料项目资料 用于实战ChatgptAI技术 源代码 供参考(代码+使用说明) Chatgpt学习资料项目资料 用于实战ChatgptAI技术 源代码 供参考(代码+使用说明)
好的,下面是一个简单的 Android Binder Demo。 首先,我们定义一个 AIDL 接口文件 `IDemoService.aidl`,它包含一个方法 `int add(int a, int b)`,用于计算两个整数的和。 ```aidl // IDemoService.aidl interface IDemoService { int add(int a, int b); } ``` 然后,我们实现这个接口,创建一个名为 `DemoService` 的服务类,它继承自 `IDemoService.Stub`,实现 `add()` 方法。 ```java // DemoService.java public class DemoService extends IDemoService.Stub { @Override public int add(int a, int b) throws RemoteException { return a + b; } } ``` 接下来,我们创建一个 `Service` 类 `DemoServiceClass`,并在其中实现 `onBind()` 方法,返回 `DemoService` 对象。 ```java // DemoServiceClass.java public class DemoServiceClass extends Service { private DemoService demoService; @Override public void onCreate() { super.onCreate(); demoService = new DemoService(); } @Nullable @Override public IBinder onBind(Intent intent) { return demoService; } } ``` 最后,在 `AndroidManifest.xml` 中声明服务。 ```xml <!-- AndroidManifest.xml --> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.binderdemo"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <!-- 声明 DemoServiceClass --> <service android:name=".DemoServiceClass" /> <activity android:name=".MainActivity" android:theme="@style/AppTheme.NoActionBar"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest> ``` 现在,我们可以在 `MainActivity` 中创建一个远程服务连接,调用 `add()` 方法并显示结果。 ```java // MainActivity.java public class MainActivity extends AppCompatActivity { private IDemoService demoService; private boolean connected = false; private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName componentName, IBinder iBinder) { demoService = IDemoService.Stub.asInterface(iBinder); connected = true; } @Override public void onServiceDisconnected(ComponentName componentName) { demoService = null; connected = false; } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Intent intent = new Intent(this, DemoServiceClass.class); bindService(intent, connection, Context.BIND_AUTO_CREATE); Button button = findViewById(R.id.button); final TextView result = findViewById(R.id.result); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (connected) { try { int a = Integer.parseInt(((EditText) findViewById(R.id.input1)).getText().toString()); int b = Integer.parseInt(((EditText) findViewById(R.id.input2)).getText().toString()); int sum = demoService.add(a, b); result.setText(String.valueOf(sum)); } catch (RemoteException e) { e.printStackTrace(); } } else { result.setText("Service not connected"); } } }); } @Override protected void onDestroy() { super.onDestroy(); unbindService(connection); } } ``` 这就是一个简单的 Android Binder Demo。它演示了如何创建一个远程服务,实现 AIDL 接口并将其绑定到 Activity。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值