现在的位置: 首页 > 综合 > 正文

Tasky范例解析

2019年10月03日 ⁄ 综合 ⁄ 共 4730字 ⁄ 字号 评论关闭

  从官网上下载Tasky范例,解压缩后编译并运行后,得到一个任务管理程序,这个程序可以实现本地任务数据的增删改查功能,数据保存在sqlite中。并在ListView中显示任务数据。

  一、数据接口Tasky.Core.Android模块

  在这个模块中定义一个任务类Task、封装针对Task类进行sql数据操作的TaskDatabase类、封装针对Task操作的单例TaskRepositoryADO类(创建sqllite数据库文件、保存、修改、查询、删除Task实例的方法)、TaskManager类调用TaskRepositoryADO单例来提供数据增删改查操作方法。

  各个类的作用:

  • Task类:与数据库表Tasks相对应的类(实体类定义)
  • TaskDatabaseADO类:在构造函数中编写sql创建sqlite数据库文件,并编写sql实现对Task实例的增删改查。是数据操作对象(实体关系映射)。
  • TaskRepositoryADO类:提供了操作Task类实例的方法,并在构造函数中构造TaskDatabaseADO实例。这个类对数据操作进一步封装,并创建出sqlite文件。(数据访问层)
  • TaskManager类:使用TaskRepositoryADO中的方法,创建操作Task类实例的方法。其实直接使用TaskRepositoryADO就可以完成数据操作了,之所以引入这个类,应该是为了后期程序的扩展性,比如把数据存放到服务器,则在创建一个与TaskRepositoryADO类功能平行的TaskRepositoryService类,修改TaskManager类调用新类提供的数据操作方法,从而实现不变动其他代码单元情况下完成对应用程序的功能扩展。(业务逻辑层)

  这个模块中需要注意的地方如下:

  • 创建sqlite数据库的方法:

public TaskDatabase (string dbPath)
{
string output = "";
path = dbPath;

bool exists = File.Exists (dbPath);
if (!exists) {
connection = new SqliteConnection ("Data Source=" + dbPath);
connection.Open ();
string[] commands = new string[] { 
"CREATE TABLE [Item] (_id INTEGER PRIMARY KEY ASC, Name NTEXT, Notes NTEXT, Done INTEGER);"
};
foreach (var command in commands) {
using (var c = connection.CreateCommand ()) {
c.CommandText = command;
c.ExecuteNonQuery ();
}
}
} else {

}
Console.WriteLine (output);
}

  其实就是配置SqliteConnection实例,指定Data Source后打开连接,执行Create Table Sql命令。

  • sqlite的ADO操作封装:

Mono.Data.Sqlite.dll中提供的SqliteConnection 、SqliteDataReader、SqliteCommand等类。

  二、Android应用程序

  这个模块是有UI界面的程序,包括显示任务列表的主界面和任务操作(添加、修改、删除)界面,下面解析一下界面操作的实现步骤。

  1、主界面

    在任务的Resources\layout目录中,双击HomeScreen.axml,打开界面设计器,可以看到一个按钮控件和一个ListView控件。接着在Screens目录双击HomeScreen.cs文件,打开源码文件,下面对代码中的要点进行简要说明。

  • Android中界面都是一个个的Activity,在设计界面的时候,要从Activity类继承一个子类并进行扩展。
  • 定义的Activity子类上方有个属性说明(或叫做注解),免去在xml配置文件中注册Activity的麻烦。

[Activity (Label = "Tasky", MainLauncher = true, Icon="@drawable/icon")]
public class HomeScreen : Activity {

//其他代码

}

这里属性指定了这个Activity是项目的默认启动Activity,并指定其图标和标题。

  • 从Activity类继承子类时,除了定义自己的数据成员、函数成员外,还需要重写一些重要的方法:

protected override void OnCreate (Bundle bundle)//Activity实例创建的时候执行,用于初始化界面元素和数据成员
{
base.OnCreate (bundle);

// set our layout to be the home screen
SetContentView(Resource.Layout.HomeScreen);

//其他代码

}

这里调用了SetContentView函数指定这个Activity加载Resources\layout目录中设计的界面。并使用FindViewById<T>函数获取界面中的元素实例,为这些元素实例绑定事件、做初始化等操作。

protected override void OnResume ()//界面需要刷新的时候触发,比如Activity第一次显示或覆盖在上方的Activity被关闭后需要重新绘制界面时执行这个函数。
{
base.OnResume ();

tasks = TaskManager.GetTasks();

// create our adapter
taskList = new Adapters.TaskListAdapter(this, tasks);

//Hook up our adapter to our ListView
taskListView.Adapter = taskList;
}

这个方法时界面需要刷新的时候自动调用的,因此将界面中的ListView控件与任务数据关联代码写在这里。首先调用上面数据操作模块中提供的方法获取所有Task对象,创建TaskListAdapter实例,并赋给界面的ListView控件的Adapter属性。这里是从数据库中从新查询所有任务数据的,保证在任务编辑Activity关闭后,从数据库中获取到最新的任务数据。

  • 任务编辑Activity与HomeScreenActivity实现方式相似。
  • 启动另外一个Activity的方式:

不需要传递参数可使用函数:StartActivity(typeof(Activity类名称));

需要传递参数则使用:

var taskDetails = new Intent (this, typeof (TaskDetailsScreen));
taskDetails.PutExtra ("TaskID", tasks[e.Position].ID);
StartActivity (taskDetails);

需要子Activity返回值的调用方式:

//第二参数为 requestcode(请求编码),主要是设定让 OnActivityResult 可以判断当初发出的动机(区分OnActivityResult函数是针对哪个请求触发的)
StartActivityForResult(typeof(Activity类名称), 1);

接着重写方法:

protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
        {
            base.OnActivityResult(requestCode, resultCode, data);
            //如果当初的发的requestCode =1
            if (requestCode == 1 && resultCode == Result.Ok)
            {
                Toast.MakeText(this, "选取结果(OnActivityResult):" + data.GetStringExtra("hero"), ToastLength.Short).Show();
            }
        }

子Activity要返回值必按如下方式设置返回值:

var intent = new Intent(this, typeof(Activity1));//第二个参数指定目标Activity实例的类型信息,这样可以让这种类型的Activity实例都触发执行OnActivityResult函数
                //放入一个key 为hero 值为 黑寡妇
                intent.PutExtra("hero", "黑寡妇");
                //状态设为OK
                SetResult(Result.Ok, intent);
                //呼叫后将关闭此窗口
                Finish();

  • 最后重点说明ListView怎么和数据做绑定,怎么指定ListView每行数据显示的格式。所有的一切都是由ListView的Adapter属性决定的,需要从BaseAdapter类中继承一个自定义的适配器。

public class TaskListAdapter : BaseAdapter<Task> {......}

        在类的构造函数中将ListView所在Activity实例、要显示的数据集合传递过来,并存储在私有数据成员中。接着重写几个关键虚方法。

public override Task this[int position]
{
get { return tasks[position]; }
}

public override long GetItemId (int position)
{
return position;
}

public override int Count
{
get { return tasks.Count; }
}

//这个方法最为关键,指定每行数据要显示的UI界面,以及这个UI界面中可视化控件显示的内容
public override Android.Views.View GetView (int position, Android.Views.View convertView, Android.Views.ViewGroup parent)
{
// 获取当前位置上要显示的数据对象
var item = tasks[position];

//如果convertView 非空则重用,否则从Resources\layout目录中加载一个设计好的视图界面,这样可以提高界面刷新效率
var view = (convertView ?? 
context.LayoutInflater.Inflate(
Resource.Layout.TaskListItem, 
parent, 
false)) as LinearLayout;

// 获取视图上的UI控件引用
var txtName = view.FindViewById<TextView>(Resource.Id.NameText);
var txtDescription = view.FindViewById<TextView>(Resource.Id.NotesText);

//设置UI控件显示的值
txtName.SetText (item.Name, TextView.BufferType.Normal);
txtDescription.SetText (item.Notes, TextView.BufferType.Normal);

//返回视图
return view;
}

抱歉!评论已关闭.