• Mono for Android开发调研笔记


    • 安装完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 }, nullnullnullnullnull);
    //新增数据
    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


  • 相关阅读:
    10. Regular Expression Matching
    9. Palindrome Number
    6. ZigZag Conversion
    5. Longest Palindromic Substring
    4. Median of Two Sorted Arrays
    3. Longest Substring Without Repeating Characters
    2. Add Two Numbers
    链式表的按序号查找
    可持久化线段树——区间更新hdu4348
    主席树——树链上第k大spoj COT
  • 原文地址:https://www.cnblogs.com/netfocus/p/2729689.html
Copyright © 2020-2023  润新知