Closed renyuzhuo closed 4 years ago
你可以拉取一下github上的最新版本。应该已经修复了。
你可以拉取一下github上的最新版本。应该已经修复了。
经确认,最新代码还是有问题。
// info.wxml
<view class="container">
<towxml nodes="{{article}}"/>
</view>
//info.js
let result = app.towxml(articleData.data, 'markdown');
//设置数据
_ts.setData({
article: result,
isLoading: false
});
下面是所要解析的 Markdown 全文(谢谢啦!)
这篇文章题目叫“【用 Kotlin 写 Android】用 Kotlin 写 Android Hello World”,主要介绍一用 Kotlin 写出来的 Hello World 究竟与用 Java 写有什么区别,并会介绍一些概念和 Kotlin 的具体实现。
一个控件定义后,在代码中不需要通过 findViewById 来讲程序对象和 xml 中布局绑定起来,而是可以直接使用使用 xml 中控件 id 直接操纵控件,这个时候会提示引入 import kotlinx.android.synthetic.main.activity_main.*
的依赖,这样可以说相当方便,去除了那些没什么大意义的模板代码,减少代码量,使结构更清晰。相信你已经看过很多地方介绍 Kotlin 都会说这是它很大的一个优点,但我想说的还包括:如果你在 setContentView(R.layout.activity_main)
中加载了一个布局文件,但是你在下面使用布局文件中 id 直接去操纵控件时,id 写错了,写成了一个在 activity_main
中根本不存在的一个 ID,会不会有问题?答案是会挂掉,可以理解,操作了不属于自己界面的元素,会报 Crash:Attempt to invoke virtual method * on a null object reference
;那如果两个界面 id 一致,但是在 import
时写错包了,会有问题吗?经试验,是没有问题的,这是不是很奇怪?其实这是因为 Android 中,在 R 文件中将资源文件都映射成一个 int
整数,存储在不同 R 文件的静态内部类里面,因此两个 id 其实在 R 文件中用一个值表示了。同理,如果其他的一些资源文件被同样映射,即使写错了,也可能正常运行。PS:不过一般没有理由把这个写错。
我们通过 id 可以找到对应的 View,为什么在 Java 中就不可以呢?这个 include 就是怎么完成这个的呢?答案是这个 include 不仅仅是简单的 include,而是因为在 build.gradle 加入了扩展 plugin: kotlin-android-extensions
,而这个扩展 plugin 其实是会编译生成一些额外代码的,那我们就把编译出来字节码文件进行反编译,看看反编译出来了点什么:
再对比一下源文件:
我们可以看到:setContentView(2131296283),将 2131296283 转换成十六进制是 0x7f09001b,在 R 文件中:
public static final class layout {
public static final int activity_main=0x7f09001b;
}
同时也不存在直接用 id 直接操作 View,而是也通过 findViewById() 来获取 View,并且这里还有一个 HashMap 进行优化,并且 id.my_app_text 也是 R 文件中的,因此在源文件中 import 错文件也不会报错:
public View _$_findCachedViewById(int var1) {
if (this._$_findViewCache == null) {
this._$_findViewCache = new HashMap();
}
View var2 = (View)this._$_findViewCache.get(var1);
if (var2 == null) {
var2 = this.findViewById(var1);
this._$_findViewCache.put(var1, var2);
}
return var2;
}
我们还看到 println(testNull?.length)
最后被反编译出来是:System.out.println(var3);
,在 Kotlin 标准库中 println 的定义是:
/** Prints the given message and newline to the standard output stream. */
@kotlin.internal.InlineOnly
public inline fun println(message: Any?) {
System.out.println(message)
}
因此也就是一些边准库的简单写法,在编译后恢复成了正常 Java 代码的写法。我们接着看反编译出来的下半部分:
这里有静态类 MainActivity.Companion,对应的是 Kotlin 中的伴随对象,伴随对象内的变量是所有类共用的属性,类似于 static 的含义,在反编译后的代码看,也确实是用 static final 对象实现的:public static final MainActivity.Companion Companion = new MainActivity.Companion((DefaultConstructorMarker)null);
我们还注意到:val TAG: String? = MainActivity::class.simpleName
最后被反编译后的代码是:private static final String TAG = Reflection.getOrCreateKotlinClass(MainActivity.class).getSimpleName();
,Reflection 是反射的意思,由 Kotlin 类映射到 Java 对象。在写前一段代码后会报警告说需要引入 org.jetbrains.kotlin:kotlin-reflect:1.2.31
,这里我们知道其实了其实它最后用到了 Kotlin 类 Reflection 和方法,不引入包就会报 kotlin.jvm.KotlinReflectionNotSupportedError: Kotlin reflection implementation is not found at runtime. Make sure you have kotlin-reflect.jar in the classpath
的错误也就可以理解了。
最后我们看一下:
var testNull: String? = null
println(testNull?.length)
var testNull: String? = "213"
println(testNull?.length)
var testNull: String? = null
if ((System.currentTimeMillis() % 2) == 0L) {
testNull = "123"
} else {
testNull = null
}
println(testNull?.length)
最后被编译成:
String testNull = (String)null;
Object var3 = null;
System.out.println(var3);
String testNull = "213";
Integer var3 = testNull.length();
System.out.println(var3);
String testNull = (String)null;
if (System.currentTimeMillis() % (long)2 == 0L) {
testNull = "123";
} else {
testNull = (String)null;
}
Integer var3 = testNull != null ? testNull.length() : null;
System.out.println(var3);
有一定的优化,如果在编译时就能确定值,直接简化,否则就是正常转换,其中 ?.
最后其实就是转换成了 if != null
的判断。
还有一个知识点是 Lambdas 表达式其实依旧是还原成最基本的 Java 代码,也包含 new OnClickListener
。
到这里,我们展示了一个最简单的 Hello World 程序,可以看出因为 Kotlin 也是运行在 JVM 上的,因此也需要符合字节码规范,因此反编译后生成的代码就会和直接用 Java 写有很多相似的部分,只不过直接写 Kotlin 的时候,Kotlin 插件或者是库帮我们完成了一些工作,我们接下来一些东西还会类似去分析。
经过测试,样式正常呀。请参考文档,重新构建呢!
我查了一下,找到原因了,是我使用的问题,我项目 css 文件中有 containe 属性,设置了:
display: flex;
我在升级时忽略了,谢谢了!
从 2.x 升级上来之后,发现原来合适的样式变为了不合适,图片变为特别宽超出屏幕范围。
但是很抱歉,由于特殊原因,暂时无法提供更多信息。