• 安装完Mono for Android(简称:MonoDroid)之后,可以用MonoDevelop或Visual Studio来开发Mono for Android应用程序;目前只能在模拟器上调试和部署,必须购买后才能在真机上调试和部署;目前遇到的最大的问题是:模拟器上调试速度非常慢,通过单步调试每一行代码都需要几秒钟。有人开了个帖子抱怨以及一些回复的相关讨论:http://mono-for-android.1047100.n5.nabble.com/Free-version-Emulator-only-Bye-bye-td5091443.html,另外,如果购买了正式版,那支持直接用设备来调试的相关文章介绍:http://docs.xamarin.com/android/tutorials/debug_on_device
  • MonoDroid应用程序,应该说所有的Android应用程序只要在处理5秒后还未完成,则会自动提示用户“应用程序无响应,是否结束应用”类似这样的提示信息。所以我们一般在处理一些可能比较耗时的操作时,比如与服务器进行通信请求数据或Post数据。这里操作都需要通过异步的方式来完成;
  • MonoDroid提供的API与原生Java平台下的Android开发基本一致,类的名称以及方法名称都保持一致,这样只要会开发原生的Android应用,那在MonoDroid下也可以开发;
  • 虽然说MonoTouch, MonoDroid可以允许我们用C#来开发在IOS以及Android应用,但是并不是所有的代码都只要用c#写一次就可以在这两个平台上跑了。实际上,能重用的代码也许只有业务层的代码。因为UI的实现,两种平台不同,MonoDroid下依赖于Mono.Android来实现UI,而MonoTouch下则是用另外一套不同的UI实现方式。实际上Mono更多的是考虑了与原生API一致的方式来开发UI,所以设计了两套不同的类库来实现UI架构;所以UI层的代码无法重用;另外,数据访问层,也不能共用,因为虽然都是访问sqlite,但是Mono在这两个平台上分别对应实现的API不同,MonoTouch下使用:MonoTouch.CoreData,而MonoDroid下使用Mono.Data.Sqlite。当然我们还是可以将数据访问层进行抽象,比如抽象成IRepository,然后业务层调用IRepository的接口即可,IRepository的具体实现需要基于不同平台分别实现;
  • 之前可以在Windows上跑的Castle框架在MonoDroid上不再支持,编译会遇到错误,因为Castle程序集依赖于System.Configuration这个程序集,但是在MonoDroid平台上没有这个程序集;MomoDroid平台上支持的.Net程序集有限,见下面的介绍。基于这个原因,但是又希望能像以前那样使用某个IOC框架,所以找了一个跨各种手机平台的轻量级开源Ioc框架(TinyIoC),该框架非常小,只有一个cs文件就能使用,使用后感觉效果还不错,基本容器功能都支持了。git开源项目地址:https://github.com/grumpydev/TinyIoC
  • log4net在MonoDroid上也不支持,因为:Log4Net uses classes in .Net namespaces such as System.Web, and System.Diagnostics that are not yet implemented in Mono for Android. 不过幸好,Android平台自带了一个Log记录器,在MonoDroid下可以使用Android.Util.Log来记录日志。如果是用Visual Studio来开发,则可以直接在VS的Output窗口看到日志,另外VS还有一个专门的窗口(View -> Other Windows -> Android Device Logging)用来查看Android记录的日志。另外,也可以通过命令行的方式查看日志,定位到目录:C:\Program Files (x86)\Android\android-sdk\platform-tools,执行命令:adb logcat,详细方法可以参考:http://docs.xamarin.com/android/advanced_topics/android_debug_log
  • MonoDroid的数据库是用sqlite,目前内置支持两种数据访问方式:原生方式(游标的方式)以及ADO.NET类似的接口,使用起来ADO.NET的方式非常简单,我们只需要引用:Mono.Data.SQLite这个程序集就能像ADO.NET那样来访问sqlite数据库了。
游标方式举例:
//查询数据
ICursor cursor = this.db.Query(DatabaseTable, new[] { KeyRowId, KeyTitle, KeyBody }, null, null, null, null, null);
//新增数据
var initialValues = new ContentValues();
initialValues.Put(KeyTitle, title);
initialValues.Put(KeyBody, body);
this.db.Insert(DatabaseTable, null, initialValues);
//更新数据
var args = new ContentValues();
args.Put(KeyTitle, title);
args.Put(KeyBody, body);
this.db.Update(DatabaseTable, args, KeyRowId + "=" + rowId, null);
//删除数据
this.db.Delete(DatabaseTable, KeyRowId + "=" + rowId, null);
//事务支持

this.db.BeginTransaction(); //Start a transaction.
try {
    var result = func(); //Do update db operations.
    db.SetTransactionSuccessful();    //tell db the update operations successfully.    
    return result;
} catch {
    //Error in between database transaction
}finally {
    //commit the transaction. 
    //if the setTransactionSuccessful method have not been called, then the transaction will auto rollback.    
    db.EndTransaction();  
}
ADO.NET方式举例,(需要引用:Mono.Data.Sqlite)
//查询数据

public static IEnumerable<Note> GetAllNotes()
{
    var sql = "SELECT * FROM ITEMS;";     using (var conn = GetConnection())
    {
        conn.Open();         using (var cmd = conn.CreateCommand())
        {
            cmd.CommandText = sql;             using (var reader = cmd.ExecuteReader())
            {
                while (reader.Read())
                    yield return new Note(reader.GetInt32(0), reader.GetString(1), reader.GetDateTime(2));
            }
        }
    }
}
//新增和更新数据

public static void SaveNote(Note note)
{
    using (var conn = GetConnection())
    {
        conn.Open();         using (var cmd = conn.CreateCommand())
        {             if (note.Id < 0)
            {
                // Do an insert
                cmd.CommandText = "INSERT INTO ITEMS (Body, Modified) VALUES (@Body, @Modified); SELECT last_insert_rowid();";
                cmd.Parameters.AddWithValue("@Body", note.Body);
                cmd.Parameters.AddWithValue("@Modified", DateTime.Now);                 note.Id = (long)cmd.ExecuteScalar();
            }
            else
            {
                // Do an update
                cmd.CommandText = "UPDATE ITEMS SET Body = @Body, Modified = @Modified WHERE Id = @Id";
                cmd.Parameters.AddWithValue("@Id", note.Id);
                cmd.Parameters.AddWithValue("@Body", note.Body);
                cmd.Parameters.AddWithValue("@Modified", DateTime.Now);                 cmd.ExecuteNonQuery();
            }
        }
    }
}
//删除数据

public static void DeleteNote(Note note)
{
    var sql = string.Format("DELETE FROM ITEMS WHERE Id = {0};", note.Id);     using (var conn = GetConnection())
    {
        conn.Open();         using (var cmd = conn.CreateCommand())
        {
            cmd.CommandText = sql;
            cmd.ExecuteNonQuery();
        }
    }
}
//事务支持

using (var conn = GetConnection ()) {
    conn.Open ();
    var transaction = conn.BeginTransaction();
    try
    {
        //Do db operations.
        transaction.Commit();
    }
    catch
    {
        transaction.Rollback();
    }
}
  • ORM,NHibernate不能运行在Mono for Android上,不过手机应用的业务逻辑相对简单,ORM的需求优先级应该不是很急,暂时可以通过上面的数据访问方式来访问sqlite数据库。
  • 类库方面,目前支持的.net类库有限,主要有以下几个:

 1 mscorlib
 2 System    包含System.Net命名空间,支持HttpWebRequest, HttpWebResponse,这两个类可以实现与服务器端通信
 3 System.Core   包含IO, LINQ, Collections,etc
 4 System.Data   该类库实现了ADO.NET的相关基础架构,如DataReader, DataAdapter, Connection, Command, etc.
 5 System.Data.Services.Client
 6 System.EnterpriseServices
 7 System.Json   提供了简单的JSON序列化和反序列化支持
 8 System.Numberics
 9 System.Runtime.Serialization
10 System.ServiceModel
11 System.ServiceModel.Web
12 System.Transactions  提供事务支持,包括分布式事务
13 System.Web.Services
14 System.Xml
15 System.Xml.Linq
16 Microsoft.CSharp
17 //以下几个是Android开发需要的类库
18 Mono.Android    MonoDroid核心类库,该类库中提供的API与原生的JAVA API基本一致,所以使用起来很方便;
19 Mono.Android.Export
20 Mono.Android.GoogleMaps
21 Mono.Android.Support.v4
22 Mono.CompilerServices.SymbolWriter
23 Mono.CSharp
24 Mono.Data.SQLite  提供封装了Sqlite数据库的ADO.NET接口支持
25 Mono.Data.Tds
26 Mono.Security
  • 与服务器通信,可以像平时一样通过HttpWebRequest或WebClient来发送请求。以下代码设计了一个通用的通过异步的方式发送HttpWebRequest

/// <summary>
/// 异步发送HttpWebRequest
/// </summary>
/// <param name="cookie"></param>
/// <param name="url"></param>
/// <param name="postData"></param>
/// <param name="callback"></param>
public static void SendHttpPostRequest(Cookie cookie, string url, string postData, Action<HttpWebResponse> callback)
{
    //解决https下的证书问题
    HttpRequestCredentialHelper.SetDefaultCredentialValidationLogic();
    var request = HttpWebRequest.Create(url) as HttpWebRequest;
    //设置请求类型为POST
    request.Method = "POST";     //设置Post的数据
    if (!string.IsNullOrEmpty(postData))
    {
        request.ContentLength = postData.Length;
        request.ContentType = "application/x-www-form-urlencoded";
        using (var writer = new StreamWriter(request.GetRequestStream()))
        {
            writer.Write(postData);
            writer.Close();
        }
    }     //将Cookie放入请求,以让服务器知道当前用户的身份
    var container = new CookieContainer();
    request.CookieContainer = container;
    if (cookie != null)
    {
        container.SetCookies(new Uri(Constants.ROOT_URL), string.Format("{0}={1}", cookie.Name, cookie.Value));
        var logger = DependencyResolver.Resolve<ILoggerFactory>().Create(typeof(HttpWebRequestHelper));
        logger.InfoFormat("HttpWebRequest CookieName:{0}, Value:{1}", cookie.Name, cookie.Value);
    }     //异步发送请求
    request.BeginGetResponse(new AsyncCallback(asyncResult =>
    {
        var httpRequest = asyncResult.AsyncState as HttpWebRequest;
        using (var response = httpRequest.EndGetResponse(asyncResult) as HttpWebResponse)
        {
            callback(response);
        }
    }), request);
}
 

发送请求示例代码:


HttpWebRequestHelper.SendHttpPostRequest(null, url, postData,
response =>
{
    var response = HttpWebRequestHelper.GetTextFromResponse(response);     //这里处理HttpWebResponse     //如果要反问UI相关元素,则需要封装为一个委托然后在RunOnUiThread方法内执行
    RunOnUiThread(() =>
    {
        var folders = _taskFolderService.GetAllTaskFolders();
        _listView.Adapter = new TaskFolderAdapter(this, Resource.Layout.TaskFolderListItem, folders.ToArray());
    });
});
  • 分层架构,我觉得我们可以采用以下的分层架构:
    • UI  界面层,MonoTouch,MonoDroid分别实现
    • Model  模型层,实现核心业务逻辑,代码可重用,如果采用DDD领域模型来实现,则可以包括:Service,Aggregate,Entity,VO,IRepository
    • Model.Infrastructure  基础框架层,实现公共基础代码,供上层调用,如DI,log,configuration,httprequest, constants, etc
    • Model.Repositories  仓储实现层,对Model层的IRepository接口的实现,不同平台采用不同实现

更多介绍关于Mono for Android开发的文章:

http://www.cnblogs.com/liping13599168/archive/2012/06/10/2543549.html

这一篇是介绍关于开发原生Android应用的文章,基本上文章中提到的方法也同样适用于Mono for Android

http://blog.csdn.net/wlanye/article/details/7199831

Mono for Android开发调研笔记的更多相关文章

  1. android开发学习笔记000

    使用书籍:<疯狂android讲义>——李刚著,2011年7月出版 虽然现在已2014,可我挑来跳去,还是以这本书开始我的android之旅吧. “疯狂源自梦想,技术成就辉煌.” 让我这个 ...

  2. Android开发自学笔记(Android Studio1.3.1)—3.Android应用结构解析

    一.R文件是什么?      如上图所示,我们可以通过findViewById方法通过传入R.id.show找到我们的TextView元素,findViewById方法也很好理解,从View中通过Id ...

  3. 搭建Mono for Android开发环境(用离线版)

    上面为我现在的离线版的安装包内容(不知道为什么上传的图名字显示不出来,郁闷),这些文件可以到http://pan.baidu.com/s/1ntM8U4T这里去下载: 安装步骤如下: 1)jdk-6u ...

  4. Android开发自学笔记(基于Android Studio1.3.1)—1.环境搭建(转)

    一.引言    本套学习笔记的开发环境是Windows 10 专业版和Android Studio 的最新版1.3.1. Android Studio 是一个Android开发环境,基于Intelli ...

  5. 【Android开发高手笔记】Dagger2和它在SystemUI上的应用

    和人类需要群居一样,程序界的进程.线程也需要通信往来.它们的交流则依赖模块之间.文件之间产生的关系.如何快速地搞清和构建这种关系,同时还能减轻彼此的依赖,需要开发者们认真思考. 我们将这种需求称之为依 ...

  6. Android开发自学笔记(Android Studio)—4.1布局组件

    一.引言 Android的界面是有布局和组件协同完成的,布局好比是建筑里的框架,而组件则相当于建筑里的砖瓦.组件按照布局的要求依次排列,就组成了用户所看见的界面.在Android4.0之前,我们通常说 ...

  7. Android开发问题笔记

    1.Toolbar问题:最低版本15,必须使用support,才能使用Toolbar,Toobar是5.0引入的 2.BottomTab:这个用TabLayout解决了 3.后端API最好采用一个成熟 ...

  8. 【转】Android开发学习笔记:5大布局方式详解

    Android中常用的5大布局方式有以下几种: 线性布局(LinearLayout):按照垂直或者水平方向布局的组件. 帧布局(FrameLayout):组件从屏幕左上方布局组件. 表格布局(Tabl ...

  9. 【Android开发学习笔记之一】5大布局方式详解

    Android中常用的5大布局方式有以下几种: 线性布局(LinearLayout):按照垂直或者水平方向布局的组件. 帧布局(FrameLayout):组件从屏幕左上方布局组件. 表格布局(Tabl ...

随机推荐

  1. ovirt node的安装简介

    Ovirt安装模式  支持install,update,downupdate,reinstall四种安装方式.  install:全新安装(以前未安装过ovirt node).  update:安装比 ...

  2. Iterator 和 Iterable 差别和联系

    用Iterator模式实现遍历集合  Iterator模式是用于遍历集合类的标准訪问方法.它能够把訪问逻辑从不同类型的集合类中抽象出来,从而避免向client暴露集合的内部结构. 比如,假设没有使用I ...

  3. Linux ssh密钥自动登录(转)

    在开发中,经常需要从一台主机ssh登陆到另一台主机去,每次都需要输一次login/Password,很繁琐.使用密钥登陆就可以不用输入用户名和密码了 实现从主机A免密码登陆到主机B,需要以下几个步骤: ...

  4. 在RHEL上安装Thrift(支持C++)的若干问题 » 编码无悔 / Intent & Focused

    在RHEL上安装Thrift(支持C++)的若干问题 » 编码无悔 / Intent & Focused [原创]在RHEL上安装Thrift(支持C++)的若干问题    2010年12月1 ...

  5. 上下文菜单与TrackPopupMenu

    这算是一个演示程序吧,想不到上下文菜单也是採用ON_COMMAND宏来进行消息映射,在这里,我发现一个问题:从CWnd派生的类ON_UPDATE_COMMAND_UI_RANGE似乎没有效果,不知道应 ...

  6. 你的App为什么上不了TOP10?

     App市场风起云涌.但是,却仅仅有少数几个App能成为"暴发户",很多其它的则沉淀在应用商店中无人问津. 在移动互联网时代.智能手机成为了中心. 手机之所以智能.就在于手机上 ...

  7. SQL_由创建表引出

    ***********************************************声明*************************************************** ...

  8. Java设置的读书笔记和集合框架Collection API

    一个.CollectionAPI 集合是一系列对象的聚集(Collection). 集合在程序设计中是一种重要的数据接口.Java中提供了有关集合的类库称为CollectionAPI. 集合实际上是用 ...

  9. hdu1535(最短路)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=1535 题意:给你一个源点,让你从这里派发n个学生去其余的n-1个站点去邀请人们去CSS,然后再返回CS ...

  10. SEAndroid安全机制中的进程安全上下文关联分析

    前面一篇文章分析了文件安全上下文关联过程.可是在SEAndroid中,除了要给文件关联安全上下文外,还须要给进程关联安全上下文.由于仅仅有当进程和文件都关联安全上下文之后,SEAndroid安全策略才 ...