Android应用插件化开发中自定义View基础插件遇到的问题

        Android应用插件化开发介绍了基于DexClassLoader和Fragment的android插件开发基本想法.宿主应用提供FragmentActivity框架用于加载每个F插件中提供的诸多Fragment,插件的DexClassLoader以及Context、Resources都可以在FragmentActivity、Fragment内部统一构造处理(具体可以参考Activity和Fragment生命周期自行设计,源码涉及到公司隐私)。

    我们在开发过程中,多个Fragment插件都要公用的基础插件,它可以是纯代码的apk,也可以是自定义View的(带资源的)apk。对于纯代码的基础插件,直接使用ClassLoader加载即可,没有任何问题。但对于类似自定义View的公共基础插件apk,此时就会存在两个android平台限制的问题。

    1.自定义View一般都会在资源中添加自定义属性,即在/values/attrs.xml文件中添加如下自定义属性。下面的例子是CircleImageView的自定义属性。

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="CircleImageView">
        <attr name="border_width" format="dimension" />
        <attr name="border_color" format="color" />
    </declare-styleable>
    
</resources>
  

    可以使用这些自定义属性达到简便的布局复用,

<com.test.widget.CircleImageView
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/iv_head_image"
    android:layout_width="36dp"
    android:layout_height="36dp"
    android:layout_alignParentLeft="true"
    android:layout_centerVertical="true"
    android:scaleType="centerCrop"
    android:src="@drawable/ic_avatar"
    app:border_color="#f7f7f7f7"
    app:border_width="2dp" />

    如果要使用 CircleImageView的自定义属性,就需要将其attrs.xml中生命的CircleImageView的自定义属性拷贝到对应的Fragment插件工程中。不然无法找到border_color和border_width两个属性的定义。

    然后问题又来了,如果拷贝了CircleImageView的自定义attrs属性后,Fragment插件和CircleImageView自定义View基础插件,在分别打包apk,其中border_color和border_width两个属性所定义的id值很可能会不一样。也就是说Fragment插件中设置的border_color和border_width两个属性,在CircleImageView插件中无法正确解析出来,导致设置失效。

    对于较为简单的Fragment插件,其中没有其他attrs属性定义的话,此时Fragment插件和CircleImageView自定义View基础插件中CircleImageView的自定义属性对应的id值是相同的,可以正常使用。但复杂的Fragment插件怎么办啊?


    2.CircleImageView相对来说很简单,没有复杂的内部布局。如果某个自定义View组件,很复杂,其中不仅仅有attrs属性,而且其内部布局也较为复杂,其中包含较多内部view id。假设该自定义View名称为CustomViewGroup,在它顶部是如下布局。

<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android" >

    <FrameLayout
        android:id="@+id/fl_inner"
        android:layout_width="wrap_content"
        android:layout_height="fill_parent"
        android:background="@color/bg_color"
        android:paddingBottom="@dimen/header_footer_top_bottom_padding"
        android:paddingLeft="@dimen/header_footer_left_right_padding"
        android:paddingRight="@dimen/header_footer_left_right_padding"
        android:paddingTop="@dimen/header_footer_top_bottom_padding" >

        <ImageView
            android:id="@+id/image"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center" />

        <ProgressBar
            android:id="@+id/progress"
            style="?android:attr/progressBarStyleSmall"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:indeterminate="true"
            android:visibility="gone" />
    </FrameLayout>

</merge>

某个Fragment插件的Fragment使用该 CustomViewGroup 构造其界面,并在 CustomViewGroup中一些布局

<com.test.widget.CustomViewGroup 
    xmlns:ptr="http://schemas.android.com/apk/res-auto"
    android:id="@+id/pull_refresh_scrollview"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:minHeight="1000dp" >

    <LinearLayout
        android:id="@+id/ll_first_layout"
        android:layout_width="match_parent"
        android:layout_height="fill_parent"
        android:focusable="true"
        android:focusableInTouchMode="true"
        android:orientation="vertical" >
		
		<TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="14sp" />
	</LinearLayout>	
<com.test.widget.CustomViewGroup />

    此时CustomViewGroup中包含了一个FrameLayout(id为R.id.fl_inner)和一个LinearLayout(id为R.id.ll_first_layout),由于这两个id值的R文件定义分别位于两个apk中( CustomViewGroup自定义View基础插件和Fragment插件),此时 存在一定可能性会出现R.id.fl_inner与R.id.ll_first_layout相同的场景。尼玛,然后各种奇葩问题就来了。

    (1)首先我门在Fragment中使用findViewById(R.id.ll_first_layout)的时候就会出现ClassCastException(无法将Framelayout强制转换为LinearLayout);

    (2)其次,onRestoreInstanceState()也会出错,两个View的状态恢复错乱了,即使用LinearLayout的保存状态来恢复FrameLayout。。。凡此种种啊。

看着这些个问题,立马就蛋疼了。



    对于上面说的问题1和2,尝试去寻找解决方法。

    首先想到的是android.jar的使用,所有android工程都要依赖android.jar,且android.R文件也在该jar包中。而且,我们使用系统控件时,其属性都是可以正常使用的,比如andorid::layout_width属性就在android.R文件中有申明。

    留带后续补充吧。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值