乐趣区

关于android:Android组件化项目搭建遇到的问题记录

1. ARouter 的依赖问题

  • What went wrong:

Execution failed for task ‘:app:kaptDebugKotlin’.

A failure occurred while executing org.jetbrains.kotlin.gradle.internal.KaptExecution
java.lang.reflect.InvocationTargetException (no error message)

  • Try:

Run with –stacktrace option to get the stack trace. Run with –info or –debug option to get more log output. Run with –scan to get full insights.

  • Get more help at https://help.gradle.org

BUILD FAILED in 4s
ע: ARouter::Compiler >>> AutowiredProcessor init. <<<����: ����ע�ʹ������ ‘org.jetbrains.kotlin.kapt3.base.ProcessorWrapper’ ����֧�� source �汾 ‘RELEASE_7’ ���� -source ‘1.8’ע: ARouter::Compiler The user has configuration the module name, it was [app]41 actionable tasks: 41 executed

Caused by: org.gradle.workers.internal.DefaultWorkerExecutor$WorkExecutionException: A failure occurred while executing org.jetbrains.kotlin.gradle.internal.KaptExecution

解决办法:回到 Arouter 官网的应用上,认真研读注意事项,找到起因。

1.ARouter 中的依赖注意事项

  1. 在 Base module 中增加配置

    comple 'com.alibaba:arouter-api:1.1.0'
    annotationProcessor 'com.alibaba:arouter-compiler:1.1.1'

2. 在各个模块中的 build.gradle 中的 defaultconfig 属性中退出:Java:

​```groovy
javaCompileOptions{
    annotationProcessorOptions{arguments = [moduleName:project.getName()]
    }
}

Kotlin:

kapt {
    arguments {
        // 路由框架译配置
        // module 名称
        arg("AROUTER_MODULE_NAME", project.getName())
        // 是否生成路由文档,"enable":生成文档,其余字符串不生成路由文档
        arg("AROUTER_GENERATE_DOC", "enable")
    }
}

在每个模块的 dependencies 属性须要 Arouter apt 的援用,不然无奈在 apt 中生成索引文件,无奈跳转胜利

旧版本的 Arouter 援用:

dependenceis{annotationProcessor 'com.alibaba:arouter-compiler:1.1.1'}

新版本中的 Arouter 中援用:

    // 路由框架正文处理器
    kapt "com.alibaba:arouter-compiler:$arouter_compiler_version"

Arouter 中的官网中对 kotlin 中的援用阐明:

// 能够参考 module-kotlin 模块中的写法
apply plugin: 'kotlin-kapt'

kapt {
    arguments {arg("AROUTER_MODULE_NAME", project.getName())
    }
}

dependencies {
    compile 'com.alibaba:arouter-api:x.x.x'
    kapt 'com.alibaba:arouter-compiler:x.x.x'
    ...
}
  • What went wrong:

Could not initialize class org.codehaus.groovy.runtime.InvokerHelper

解决办法:

更新 gradle 版本号 到 6.3, 之前的版本号是 gradle-5.6.4-all

改为:gradle-6.3-all.zip

https://stackoverflow.com/que…

Please make changes as per below to resolve this error.

Install Java SDK version: 14 or above.

JDK Download link: https://www.oracle.com/java/technologies/javase-jdk14-downloads.html

In gradle-wrapper.properties please use grade version 6.3 or above.

For e.g:distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-all.zip

3. 其余编译问题:

No such property: variantConfiguration for class: com.android.build.gradle.internal.variant.ApplicationVariantData

思路一:参考 stackoverffow 中的计划,批改 gradle 版本号,未果。

A failure occurred while executing org.jetbrains.kotlin.gradle.internal.KaptExecution

起因:ARouter编译问题:

> Task :app:kaptCtestKotlin FAILED
注: ARouter::Compiler >>> AutowiredProcessor init. <<< 正告: 来自正文处理程序 'org.jetbrains.kotlin.kapt3.base.ProcessorWrapper' 的受反对 source 版本 'RELEASE_7' 低于 -source '8' 注: ARou
ter::Compiler The user has configuration the module name, it was [app]
FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:kaptCtestKotlin'.
> A failure occurred while executing org.jetbrains.kotlin.gradle.internal.KaptExecution
   > java.lang.reflect.InvocationTargetException (no error message)

解决方案: 回到 Arouter 中无关 kotlin 的引入时,发现:

须要这样引入:留神版本号以最新的为准,版本号不一样的。

    // 路由框架正文处理器 https://github.com/alibaba/ARouter
    kapt "com.alibaba:arouter-compiler:1.2.2"
    api 'com.alibaba:arouter-api:1.5.0'

问题来了,组件化中如何引入?

14. 默认启动问题

06/18 15:40:14: Launching 'app' on HUAWEI HLK-AL00.
Could not identify launch activity: Default Activity not found
Error while Launching activity

解决办法:AS 革除缓存、Sync、解决模块中的资源引入问题后,最初发现 在组件中援用出了问题。

必须记得在宿主 app 中援用相应的模块。

如果呈现这个谬误日志:

Error: null, Cannot fit requested classes in a single dex file (# methods: 70124 > 65536)

解决文案:都是由依赖第三方库 jar 包引发的,能够通过批改 app 的 build.gradle 文件解决该谬误。
增加依赖:

dependencies {implementation 'com.android.support:multidex:1.0.3'}

在 defaultConfig 中增加以下属性

multiDexEnabled true

参考链接:https://www.jianshu.com/p/72d…

4. 编译阶段 注册界面没有发现实现类

ARouter::Register >>> No class implements found for interface:com/alibaba/android/arouter/facade/template/IInterceptorGroup

我的项目中的问题体现:获取不到 Fragment 中的实例,跳转失败,无奈启动首页。

解决办法:通过查阅材料,发现所依赖的模块没有在 App 宿主中进行依赖。

module-home 为例,所有 module 必须在这里进行依赖。

思路起源:

There’s no router matched!

在组件化开发过程中,我在宿主 App 模块援用模块 C 中的 Activity,始终不能胜利,界面及日志提醒 ”W/ARouter::: ARouter::There is no route match the path [/xxx/xxx], in group xxx”
最终定位起因是须要在宿主 App 的 build.gradle 中,把须要路由的模块(上例中的模块 C)引入进来。

在组件化开发中,各模块倡议不要有依赖关系。宿主 App 在打包编译时可依赖各组件,组件之间能够应用 ARouter 进行界面跳转。上例中模块 c 和 d 之间无依赖关系,然而再宿主 app 中能够进行跳转。

参考链接:https://www.jianshu.com/p/a88…

5. 网络申请

指标 IP:110.184.70.43
执行工夫:0.085(秒)
以后状态:200
返回状态:200 null

Request Header:
Content-Type : application/x-www-form-urlencoded
Content-Length : 6

Response Header:
Transfer-Encoding : chunked
Connection : close
Date : Fri, 08 May 2020 06:45:27 GMT
Content-Type : application/json;charset=UTF-8

申请中的 Content-Type 设置

1、application/x-www-form-urlencoded;charset=utf-8

    查看相干文档发现,这种 Content-type 类型是以 form 表单的模式提交数据的是基于 uri 的 percent-encoding 编码的,所以 body 中的数据会以 key=values 的模式进行序列化,而这个编码的过程中,一些特殊符号会通过 URL 转码转成如 4%D3%3F。。。等模式,这就导致了咱们后面呈现了 json 数据被做了这样的解决, 因为默认状况下 okhttp 的 Content-type 默认就是 application/x-www-form-urlencoded,这就不难解析为什么后盾以流的模式读取数据的时候拿到的数据多了个 content=,并且被编码了。

2、application/json;charset=utf-8

    这种 Content-type 的编码方式当初是十分风行的,如果你在申请的时候应用抓包工具进行抓包,你会发现,申请体外面显示的内容是一个规范的 json 串,而不会像通过 URL 转码后的数据那样。

————————————————
原文链接:https://blog.csdn.net/MonaLis…

http 协定 POST 申请头 content-type 次要的四种取值

content-type 个别只存在于 Post 办法中,因为 Get 办法是不含“body”的,它的申请参数都会被编码到 url 前面,所以在 Get 办法中加 Content-type 是无用的。

四种常见的 POST 提交数据形式

  1. application/x-www-form-urlencoded
  2. multipart/form-data
  3. application/json
  4. text/xml

6. 混同相干

写给 Android 开发者的混同使用手册

7. 打包问题相干

Task :app:minifyReleaseWithR8 FAILED
E:projectPandaappmultidex-config.pro: R8: Failed to read file: E:projectPandaappmultidex-config.pro

FAILURE: Build failed with an exception.

  • What went wrong:

Execution failed for task ‘:app:minifyReleaseWithR8’.

com.android.tools.r8.CompilationFailedException: Compilation failed to complete

8. 阿里一键登录时因为第三适配框架引发的问题

2020-05-12 17:35:51.039 10332-10466/com.tywj.buscustomerapp E/AuthSDK: java.lang.IllegalStateException: Not in applications main thread

   at me.jessyan.autosize.utils.Preconditions.checkMainThread(Preconditions.java:113)
   at me.jessyan.autosize.AutoSizeCompat.autoConvertDensity(AutoSizeCompat.java:139)
   at me.jessyan.autosize.AutoSizeCompat.autoConvertDensityBaseOnWidth(AutoSizeCompat.java:112)
   at me.jessyan.autosize.AutoSizeCompat.autoConvertDensityOfGlobal(AutoSizeCompat.java:57)
   at com.tywj.buscustomerapp.common.view.base.MyBaseActivity.getResources(MyBaseActivity.kt:64)
   at com.mobile.auth.gatewayauth.utils.b.c(Native Method)
   at com.mobile.auth.gatewayauth.utils.SupportJarUtils.startActivityForResult(SupportJarUtils.java:26)
   at com.mobile.auth.gatewayauth.a.g(Native Method)
   at com.mobile.auth.gatewayauth.ctcc.a.j(Native Method)
   at com.mobile.auth.gatewayauth.ctcc.a.a(Native Method)
   at com.mobile.auth.gatewayauth.PhoneNumberAuthHelper.b(Native Method)
   at com.mobile.auth.gatewayauth.PhoneNumberAuthHelper.a(PhoneNumberAuthHelper.java:53)
   at com.mobile.auth.gatewayauth.PhoneNumberAuthHelper$2.a(PhoneNumberAuthHelper.java:1202)
   at com.mobile.auth.gatewayauth.utils.h$a.run(Native Method)
   at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
   at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
   at java.lang.Thread.run(Thread.java:764)

解决方案:该界面勾销适配

集成阿里一键登录布局问题

2020-05-15 16:59:23.808 9430-9430/com.tywj.buscustomerapp E/AuthSDK: java.lang.IllegalStateException: ivTaobao must not be null

    at com.tywj.buscustomerapp.LoginAuthActivity$configLoginTokenPort$1.onViewCreated(LoginAuthActivity.kt:182)
    at com.mobile.auth.gatewayauth.ui.a.<init>(PnsView.java:27)
    at com.mobile.auth.gatewayauth.ui.a.<init>(PnsView.java:18)
    at com.mobile.auth.gatewayauth.LoginAuthActivity.h(Native Method)
    at com.mobile.auth.gatewayauth.LoginAuthActivity.d(Native Method)
    at com.mobile.auth.gatewayauth.LoginAuthActivity.onCreate(Native Method)
    at android.app.Activity.performCreate(Activity.java:7232)
    at android.app.Activity.performCreate(Activity.java:7221)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1272)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2964)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3119)
    at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1839)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loop(Looper.java:201)
    at android.app.ActivityThread.main(ActivityThread.java:6864)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:873)

2020-05-15 16:59:23.906 9430-9430/com.tywj.buscustomerapp E/xxxxxx: onTokenFailed:{“code”:”600023″,”msg”:” 加载自定义控件异样 ”,”requestCode”:0,”vendorName”:”CTCC”}

解决办法:kotlin 中不能间接用, 须要用 findById(R.id.xx){}

9. 混同后呈现的问题

Caused by: java.lang.NoSuchFieldException: No field mObservers in class Landroidx/lifecycle/LiveData; (declaration of ‘androidx.lifecycle.LiveData’ appears in /data/app/com.tywj.buscustomerapp-d3FzmCWoaSzUUxOl777Wtg==/base.apk!classes2.dex)

    at java.lang.Class.getDeclaredField(Native Method)
    at com.tywj.buscustomerapp.common.bus.LiveDataBus$BusMutableLiveData.a(LiveDataBus.kt:136)
    at com.tywj.buscustomerapp.common.bus.LiveDataBus$BusMutableLiveData.a(LiveDataBus.kt:127)
    at com.tywj.buscustomerapp.common.bus.LiveDataBus.a(LiveDataBus.kt:28)
    at com.tywj.buscustomerapp.user.UserFragment.l(UserFragment.kt:44)
    at com.tywj.lib.core.common.view.a.onActivityCreated(BaseFragment.kt:54)
    at androidx.fragment.app.Fragment.performActivityCreated(Fragment.java:2619)
    at androidx.fragment.app.h.a(FragmentManagerImpl.java:904)
    at androidx.fragment.app.h.l(FragmentManagerImpl.java:1238)
    at androidx.fragment.app.a.e(BackStackRecord.java:434)
    at androidx.fragment.app.h.a(FragmentManagerImpl.java:2079)
    at androidx.fragment.app.h.b(FragmentManagerImpl.java:1869)
    at androidx.fragment.app.h.c(FragmentManagerImpl.java:1824)
    at androidx.fragment.app.h.r(FragmentManagerImpl.java:1727)
    at androidx.fragment.app.h.d(FragmentManagerImpl.java:2663)
    at androidx.fragment.app.h.g(FragmentManagerImpl.java:2613)
    at androidx.fragment.app.d.a(FragmentController.java:246)
    at androidx.fragment.app.FragmentActivity.onStart(FragmentActivity.java:542)
    at androidx.appcompat.app.AppCompatActivity.onStart(AppCompatActivity.java:201)
    at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1392)
    at android.app.Activity.performStart(Activity.java:7260)
    at android.app.ActivityThread.handleStartActivity(ActivityThread.java:3008)
    at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:180)
    at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:165)
    at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:142)
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:70)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1839)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loop(Looper.java:201)
    at android.app.ActivityThread.main(ActivityThread.java:6864)
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:873) 

2020-05-19 11:23:17.105 1340-1656/? E/InputDispatcher: channel ‘d045c90 com.tywj.buscustomerapp/com.tywj.buscustomerapp.launch.SplashActivity (server)’ ~ Channel is unrecoverably broken and will be disposed!

private fun disableSticky(observer: BusObserverWrapper<in T>) {if (observer.isSticky || observer.isWithoutActiveStatus) {return}

            val classLiveData = LiveData::class.java
            val fieldObservers = classLiveData.getDeclaredField("mObservers")
            fieldObservers.isAccessible = true
            val objectObservers = fieldObservers.get(this)

            val classObservers = objectObservers.javaClass
            val methodGet = classObservers.getDeclaredMethod("get", Any::class.java)
            methodGet.isAccessible = true
            val objectWrapperEntry = methodGet.invoke(objectObservers, observer)
            var objectWrapper: Any? = null
            if (objectWrapperEntry is Map.Entry<*, *>) {objectWrapper = objectWrapperEntry.value}
            if (objectWrapper == null) {throw  NullPointerException("Wrapper can not be bull!")
            }

            val classObserverWrapper: Class<in Any> = objectWrapper.javaClass.superclass!!
            val fieldLastVersion = classObserverWrapper.getDeclaredField("mLastVersion")
            fieldLastVersion.isAccessible = true
            val fieldVersion = classLiveData.getDeclaredField("mVersion")
            fieldVersion.isAccessible = true
            val objectVersion = fieldVersion.get(this)
            fieldLastVersion.set(objectWrapper, objectVersion)
        }
    }

解决办法:更换最新的音讯组件

10. 对于键盘遮挡或下面的布局向上挪动的问题。

     <!-- 抉择地址 -->
        <activity
            android:name="com.tywj.navigation.map.NavigationSelectedAddress"
            android:windowSoftInputMode="adjustPan"  />

增加键盘属性。

adjustPan:以后窗口的内容将主动挪动以便以后焦点从不被键盘笼罩和用户能总是看到输出内容的局部。

adjustResize:该 Activity 总是调整屏幕的大小以便留出软键盘的空间。

参考链接:https://www.cnblogs.com/momos…

11. 高低切换动画实现

android 动画调换高低布局(相似导航起始地址和导航目的地切换)

public void swapViewUpDown(int upViewId, final int downViewId) {final View upView = (View) findViewById(upViewId);
        final View downView = (View) findViewById(downViewId);
        upView.animate().translationYBy(upView.getHeight()).setDuration(ANIMATION_DURATION)
        .setInterpolator(new BounceInterpolator());
        downView.animate().translationYBy(-downView.getHeight()).setDuration(ANIMATION_DURATION)
        .setInterpolator(new BounceInterpolator());
 
    }

4 种动画插值器

  • OvershootInterpolator:冲过了头回滚一点的成果
  • AnticipateInterpolator:登程前先后退一步再前冲的动画成果
  • AnticipateOvershootInterpolator:以上两种的联合
  • BounceInterpolator:自在落地后回弹的成果

参考链接:android 动画调换高低布局

12.ImageView 中旋转 180 度

应用场景:用代码管制旋转,实现动画和缩小资源图片文件应用。

  • 应用 ImageView 自带的旋转办法
<ImageView
   android:src="@drawable/common_back"
   android:layout_centerInParent="true"
   android:id="@+id/lv_common_return"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:rotation="180" />

目标,对于规定的图片,不须要雷同的图片切两次,能够间接用翻转实现。要害代码:

android:rotation="180"
  • 代码实现

    
    image.setPivotX(image.getWidth()/2);
    image.setPivotY(image.getHeight()/2);// 支点在图片核心
    image.setRotation(90);
  • 也能够用动画实现:
object RotateUtils {
    /**
     * 依据以后的状态来旋转箭头。*/
    fun rotateArrow(arrow: ImageView, flag: Boolean) {
        val pivotX = arrow.width / 2f
        val pivotY = arrow.height / 2f
        var fromDegrees = 0f
        var toDegrees = 0f
        // flag 为 true 则向下
        if (flag) {
            fromDegrees = 0f
            toDegrees = 180f
        } else {
            // 向上
            fromDegrees = 180f
            toDegrees = 360f
        }
        // 旋转动画成果   参数值 旋转的开始角度  旋转的完结角度  pivotX x 轴伸缩值
        val animation = RotateAnimation(
            fromDegrees, toDegrees,
            pivotX, pivotY
        )
        // 该办法用于设置动画的持续时间,以毫秒为单位
        animation.duration = 200
        // 设置反复次数
        //animation.setRepeatCount(int repeatCount);
        // 动画终止时停留在最初一帧
        animation.fillAfter = true
        // 启动动画
        arrow.startAnimation(animation)
    }
}
  • 另一种动画:能够应用 ImageView 配合属性动画实现

    rotateImage.animate().rotation(90);
  • 一般动画
Animation rotateAnimation  = new RotateAnimation(lastAngle, progress, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 1);
                rotateAnimation.setFillAfter(true);
                rotateAnimation.setDuration(50);
                rotateAnimation.setRepeatCount(0);
                rotateAnimation.setInterpolator(new LinearInterpolator());
                rotateImage.startAnimation(rotateAnimation);

参考:Android UI 之 ImageView 旋转的几种形式

13. 华为手机装置 app 无启动图标

问题起因:可能是在 LearnCanry 引入产生,正式打包后问题仍然存在。而 oppo、小米手机装置后显示失常。

解决办法:华为手机权限解决后,将主题设置为华为的的主题后,可见。

15. 组件化之间的 xml 资源文件问题

如果有雷同的布局等文件,肯定要删除反复的或其余命名,否则 Kotlin 中初始化时会找不到。提醒为 null

java.lang.IllegalStateException:  xxx(etFeedback) must not null

起因:user-center 组件化时有反复的资源,抵触后找不到出错。

17. 阿里一键登录时 oppo 手机在压缩打包后无奈唤醒登录页

通过日志剖析:发现无奈找到资源文件,而阿里官网却没有阐明,只得通过日志一步一步去定位。

"R.drawable.umcsdk_return_bg"
"R.drawable.umcsdk_login_btn_bg"
"R.drawable.umcsdk_uncheck_image"

最初将 umcsdk 相干的退出白名单,不压缩,问题得以终局。

    // 白名单
    whiteList = [
    // 这里的资源在局部手机(viVo、小米)中无奈唤醒,是友盟的资源文件混同了,剖析日志得出结论
            "R.drawable.umcsdk*"
            ]

留神:此处引入了 Android 资源混同工具

        classpath 'com.tencent.mm:AndResGuard-gradle-plugin:1.2.18'
退出移动版