Quantcast
Channel: かずきのBlog@hatena
Viewing all articles
Browse latest Browse all 1387

Xamarin.AndroidでContentProviderを実装する

$
0
0

SQLiteの使い方がわかったら次はContentProviderですよね。 ということで、SQLの部分はさくっと実装。

using Android.Content;
using Android.Database.Sqlite;

namespace ContentProviderSample
{
    publicclass PeopleDatabase : SQLiteOpenHelper
    {
        privateconststring DbName = "people.db";
        privateconststring TableName = "People";
        privateconststring CreateTable = @"            create table People (                _id integer primary key autoincrement,                name varchar(150)            );";
        privateconstint DatabaseVersion = 2;

        public PeopleDatabase(Context context) : base(context, DbName, new PeopleCursorFactory(), DatabaseVersion)
        {
        }
        
        publicoverridevoid OnCreate(SQLiteDatabase db)
        {
            db.ExecSQL(CreateTable);
            for (int i = 0; i < 100; i++)
            {
                var c = new ContentValues();
                c.Put("name", "tanaka" + i);
                db.Insert(TableName, null, c);
            }
        }

        publicoverridevoid OnUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
        {
        }

        public PeopleCursor GetAll()
        {
            return (PeopleCursor) this.ReadableDatabase.Query(TableName, new[] { "_id", "name" }, null, null, null, null, "_id");
        }

        public PeopleCursor GetOne(long id)
        {
            return (PeopleCursor) this.ReadableDatabase.Query(TableName, new[] { "_id", "name" }, "_id = ?", new[] { id.ToString() }, null, null, null);
        }
    }

    publicclass PeopleCursor : SQLiteCursor
    {
        public PeopleCursor(ISQLiteCursorDriver driver, string editTable, SQLiteQuery query) : base(driver, editTable, query)
        {
        }

        publiclong Id
        {
            get { returnthis.GetLong(this.GetColumnIndex("_id")); }
        }

        publicstring Name
        {
            get { returnthis.GetString(this.GetColumnIndex("name")); }
        }
    }

    publicclass PeopleCursorFactory : Java.Lang.Object, SQLiteDatabase.ICursorFactory
    {
        public Android.Database.ICursor NewCursor(SQLiteDatabase db, ISQLiteCursorDriver masterQuery, string editTable, SQLiteQuery query)
        {
            returnnew PeopleCursor(masterQuery, editTable, query);
        }
    }

}

ContentProvider

コンテンツプロバイダーを作っておくと、いろいろ便利らしいので、作っておきます。

using Android.Content;
using System;

namespace ContentProviderSample
{
    // Authorityを属性で設定する
    [ContentProvider(new[] { Authority })]
    publicclass PeopleContentProvider : ContentProvider
    {
        // URI組立に必要な人たちprivateconststring Authority = "com.example.PeopleProvider";
        privateconststring BasePath = "people";
        publicstaticreadonly Android.Net.Uri ContentUri = Android.Net.Uri.Parse("content://" + Authority + "/" + BasePath);

        // Mimeprivateconststring MimeType = "/vnd.com.example.People";

        // UriMatcherのマッチ結果privateconstint GetAll = 0;
        privateconstint GetOne = 1;

        privatestaticreadonly UriMatcher UriMatcher = CreateUriMatcher();

        // UriMatcherを生成するprivatestatic UriMatcher CreateUriMatcher()
        {
            var r = new UriMatcher(UriMatcher.NoMatch);
            r.AddURI(Authority, BasePath, GetAll);
            r.AddURI(Authority, BasePath + "/#", GetOne);
            return r;
        }

        private PeopleDatabase db;

        // 列名の定数publicstaticclass PeopleColumns
        {
            publicconststring Id = "_id";
            publicconststring Name = "name";
        }

        // 削除。とりあえず未実装publicoverrideint Delete(Android.Net.Uri uri, string selection, string[] selectionArgs)
        {
            thrownew NotImplementedException();
        }

        // Uriに応じてMimeを返す。今回は同じもの返すpublicoverridestring GetType(Android.Net.Uri uri)
        {
            switch (UriMatcher.Match(uri))
            {
                case GetAll:
                case GetOne:
                    return MimeType;
                default:
                    thrownew Java.Lang.IllegalArgumentException();
            }
        }

        // 挿入。とりあえず未実装publicoverride Android.Net.Uri Insert(Android.Net.Uri uri, ContentValues values)
        {
            thrownew NotImplementedException();
        }

        // 作成時の処理。とりあえずDB作るpublicoverridebool OnCreate()
        {
            this.db = new PeopleDatabase(this.Context);
            returntrue;
        }

        // Uriを判別して全件返すか一件返すか処理をわけるpublicoverride Android.Database.ICursor Query(Android.Net.Uri uri, string[] projection, string selection, string[] selectionArgs, string sortOrder)
        {
            switch (UriMatcher.Match(uri))
            {
                case GetAll:
                    returnthis.db.GetAll();
                case GetOne:
                    returnthis.db.GetOne(long.Parse(uri.LastPathSegment));
                default:
                    thrownew Java.Lang.IllegalArgumentException();
            }
        }

        // 更新。とりあえず未実装publicoverrideint Update(Android.Net.Uri uri, ContentValues values, string selection, string[] selectionArgs)
        {
            thrownew NotImplementedException();
        }
    }
}

なんか定型でめんどくさい感じがしますね。

使う

ListViewにとりあえず表示してみようと思います。

using Android.App;
using Android.Content;
using Android.Database;
using Android.OS;
using Android.Widget;

namespace ContentProviderSample
{
    [Activity(Label = "ContentProviderSample", MainLauncher = true, Icon = "@drawable/icon")]
    publicclass MainActivity : Activity
    {
        protectedoverridevoid OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);

            // Set our view from the "main" layout resourcethis.SetContentView(Resource.Layout.Main);

            // ListViewを取得して
            var listView = this.FindViewById<ListView>(Resource.Id.Main_ListViewPeople);

            // 取得する列名を指定してstring[] projection = new[] { PeopleContentProvider.PeopleColumns.Id, PeopleContentProvider.PeopleColumns.Name };
            // 表示列を指定string[] fromColumns = new[] { PeopleContentProvider.PeopleColumns.Name };
            // 表示先コントロールのIDを指定int[] toControlIds = new[] { Android.Resource.Id.Text1 };

            // コンテンツプロバイダーからデータを読み込む
            var loader = new CursorLoader(this, PeopleContentProvider.ContentUri, projection, null, null, null);
            var cursor = loader.LoadInBackground() as ICursor;

            // カーソルを使うアダプタを作って、ListViewに設定
            var adapter = new SimpleCursorAdapter(this, Android.Resource.Layout.SimpleListItem1, cursor, fromColumns, toControlIds);
            listView.Adapter = adapter;
        }
    }
}

見事表示できた。

f:id:okazuki:20140727233014p:plain


Viewing all articles
Browse latest Browse all 1387

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>