Xamarin.Android开发中一些不可不知的知识点

Xamarin.Android所提供的接口基本上是对原生接口的再封装,但Xamarin团队在封装时采用了C#风格,这会导致某些API的用法无法完全和原生方法对照起来。除此之外,由于Xamarin.Android并不是将C#直接翻译成JVM语言,而是引入了Mono运行时,通过ACW对Java的对象进行访问,因此某些操作也会与原生方式迥异,理解这些差异点,会让我们在开发时更加游刃有余。


Xamarin.Android的体系结构

知识点1:如何实例化Runnable接口

在原生开发中,Runnable接口的使用几乎可以说是不可避免的,因为它太常用了。在Xamarin.Android中,Runnable对应的API定义是IRunnable,一般而言,Xamarin.Android都会在接口定义的前面加个大写的I,这是Java语法规范中没有要求的。这可能会让我们有些不适应。但事实证明,这么做也是有好处的,至少我知道了不少API原来是接口,而不是类;毕竟很多时候,我们都是拿来就用,是接口还是类型,并不会产生实质性的影响,因此也就不会专门去查询是接口还是类;所以,如果在Xamarin.Android下找不到与原生对应的的API,试试在前面加个I,也许那是个接口也不一定。

对于Runnable接口这个例子,如果使用Java语法的话,我们一般是用匿名类来实现它。

  Runnable run = new Runnable() {
            @Override
            public void run() {
              //do what you want
            }
        };

但在C#中情况就有所不同了,因为C#是不支持匿名类型的。但是我们总不能每一次都去实现一个IRunnable接口的类型,那光是起名字,就很累人了。
还好,Xamarin.Android官方很周到地提供了一个Runnable类型,注意:这是个类型哦,不是接口哦。这个类型有一个接收Action委托的构造器,这样我们就可以把我们想要运行的代码包装成Action委托,利用lamda表达式就能够达成比Java的匿名类型更便捷的效果了;

IRunnable run = new Runnable(() =>{
    //do what  you want
});

知识点2:如何实例化IThreadFatory接口

在想要实例化一个线程池对象时,我发现我所使用的的ThreadPoolExecutor构造器的最后一个参数原来是个接口。

一个ThreadPoolExecutor构造器的定义

而这一次Xamarin.Android官方可没有那么温馨地为这个接口提供一个已经定义好的类型,所以我决定自己动手,丰衣足食。但是但我试图实现一个IThreadFactory类型时,出幺蛾子了。自动实现接口出来的效果是这样的。

    class MyThreadFactory : IThreadFactory {
        public IntPtr Handle => throw new NotImplementedException();

        public void Dispose() {
            throw new NotImplementedException();
        }

        public Thread NewThread(IRunnable r) {
            throw new NotImplementedException();
        }
    }

我不是只需要实现NewThread方法就行了吗?另外两个是什么鬼?
查看一下IThreadFactory的定义:


IThreadFactory的定义

比原生定义多了一个IJavaObject接口,再看看这个是什么:

IJavaObject的定义

原来IJavaObject正是ACW机制的关键,实现了对原生对象的托管,而且第一句话就开宗明义地说:“NEVER IMPLEMENT THIS INTERFACE YOURSELF”(不要自行实现该接口)。好吧,那我具体应该怎么做呢?当我想打开文中给出的文档链接查看更多信息时,却发现这个链接已经失效了。
对这个问题,我迷茫了很长时间,最后是在Stackflower上的某个回答中意外地发现了问题的答案。解决方法很简单,就是在IThreadFactory接口的同时,继承Java.Lang.Object类。

class MyThreadFactory : Java.Lang.Object, IThreadFactory {
        public Thread NewThread(IRunnable r) {
            
        }
    }

注意:这里的Object要使用全名Java.Lang.Object,否则会和C#自身的Object基类型发生冲突;然后,我们就只需要实现接口要求的方法就可以了。其它类似的接口实现也是如此这般。

知识点3:如何将某些类型转换成需要的接口对象

我发现有些Xamarin.Android对象不能够像往常一样转换成我需要的接口对象,比如下面的代码在运行时就会抛出InvalidCastException
异常:

IWindowManager windowManager = (IWindowManager)context.GetSystemService(Context.WindowService);

这个时候,我们需要换个姿势来进行类型转换,这个姿势就是正确的:

windowManager = context.GetSystemService(Context.WindowService).JavaCast<IWindowManager>();

JavaCast<TResult>是一个扩展方法,其定义如下:


JavaCast<TResult>的定义

这么做的原因如下:


大概意思就是说,这是一个黑科技,用来应对正常类型转换无法应付的情况。根据文档的描述,应该只有在向接口转换时才会出现这样的问题。所以,像从子类向父类的转换一般都是可以成功的。比如:

ViewGroup viewGroup = (subview.Parent as ViewGroup);
ViewGroup viewGroup = (ViewGroup)subview.Parent;

知识点4:如何获取对象的class

再Java开发中使用反射时,我们经常会需要获取类的class对象,原生的做法很简单:

Class c = MyClass.class;

但这个语法在C#中是不受支持的,我们需要使用一个专门的方法来实现这个功能;

    Java.Lang.Class c = Java.Lang.Class.FromType(typeof(MyClass));

当然执行该方法的前提是,目标是Java.Lang.Object的子类,不能是纯C#对象;

先讲这么多,后续还有遇到再与大家分享。

参考文献

Xamarin.Android的高级的概念和内部机制
IJavaObject的官方文档
JavaCast<TResult>的官方文档
Java.Lang.Class.FromType Method

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270