第二个项目CriminalIntent应用开发阶段总结(二)
第二个项目CriminalIntent应用开发阶段总结(二)
对话框的应用
我们为Criminal Intent 应用添加对话框,以便用户修改crime记录日期。
Google提供了AppCompat库版的AlertDialog类。要使用就需要引用android.support.v7.app.AlertDialog依赖项
。
- 创建对话框
为对话框标题添加字符串资源
<string name="date_picker_title">Date of crime:</string>
创建DialogFrangment
public class DatePickerFragment extends DialogFragment {
@Override
public Dialog onCreateDialog(Bundle saveInstanceState){
return new AlertDialog.Builder(getActivity())
.setView(v)
.setTitle(R.string.date_picker_title)
.setPositiveButton(android.R.string.ok,null)
.create();
}
}
显示对话框
private static final String DIALOG_DATE = "DialogDate";
mDateButton.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
FragmentManager manager = getFragmentManager();
DatePickerFragment dialog = DatePickerFragment
.newInstance(mCrime.getDate());
dialog.setTargetFragment(CrimeFragment.this,REQUEST_DATE);
dialog.show(manager,DIALOG_DATE);
}
});
- 设置对话框显示内容
在项目工具窗口中,以DatePicker为根,创建名为dialog_date.xml的布局文件。新布局仅包含一个View对象,即我们生成并传给setView(...)方法的DatePicker视图。
给AlertDialog添加DatePicker
View v = LayoutInflater.from(getActivity())
.inflate(R.layout.dialog_date,null);
return new AlertDialog.Builder(getActivity())
.setView(v)
- fragment间的数据传递
要传递crime日期给DatePickerFragment,需将它保存在DatePickerFragment的argumentbundle中。这样,DatePickerFragment就能直接获取它。
添加newInstance(Date)方法
private static final String ARG_DATE = "date";
private DatePicker mDatePicker;
public static DatePickerFragment newInstance(Date date){
Bundle args = new Bundle();
args.putSerializable(ARG_DATE,date);
DatePickerFragment fragment = new DatePickerFragment();
fragment.setArguments(args);
return fragment;
}
添加newInstance()方法,用DatePickerFragment.newInstance(Date)方法替换DatePickerFragment的构造方法
// DatePickerFragment dialog = new DatePickerFragment();
DatePickerFragment dialog = DatePickerFragment
.newInstance(mCrime.getDate());
获取Date对象并初始化DatePicker
Date date = (Date) getArguments().getSerializable(ARG_DATE);
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int day = calendar.get(Calendar.DAY_OF_MONTH);
mDatePicker = (DatePicker) v.findViewById(R.id.dialog_date_picker);
mDatePicker.init(year,month,day,null);
设置目标fragment
private static final int REQUEST_DATE = 0;
回调目标fragment
public static final String EXTRA_DATE =
"com.bignerdranch.android.criminalintent.date";
private void sentResult(int resultCode,Date date){
if (getTargetFragment() == null){
return;
}
Intent intent = new Intent();
intent.putExtra(EXTRA_DATE,date);
getTargetFragment()
.onActivityResult(getTargetRequestCode(),resultCode,intent);
}
响应DatePicker对话框
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data){
if (resultCode != Activity.RESULT_OK){
return;
}
if (requestCode == REQUEST_DATE){
Date date = (Date) data
.getSerializableExtra(DatePickerFragment.EXTRA_DATE);
mCrime.setDate(date);
updateDate();
}
}
private void updateDate() {
mDateButton.setText(mCrime.getDate().toString());
}
SQLite数据库
1.定义数据库
定义CrimeTable内部类
public class CrimeDbSchema {
public static final class CrimeTable{
public static final String NAME = "crimes";
}
}
定义数据表字段
public static final class Cols{
public static final String UUID = "uuid";
public static final String TITLE = "title";
public static final String DATE = "date";
public static final String SOLVED = "solved";
public static final String SUSPECT = "suspect";
}
2.创建初始数据库
创建CrimeBaseHelper类
public class CrimeBaseHelper extends SQLiteOpenHelper {
private static final int VERSION = 1;
private static final String DATABASE_NAME = "crimeBase.db";
public CrimeBaseHelper(Context context){
super(context,DATABASE_NAME,null,VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
打开SQLiteDatabase
private Context mContext;
private SQLiteDatabase mDatabase;
mContext = context.getApplicationContext();
mDatabase = new CrimeBaseHelper(mContext)
.getWritableDatabase();
创建crime数据表
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("create table " + CrimeTable.NAME + "(" + "_id integer primary key autoincrement, " +
CrimeTable.Cols.UUID + ", " +
CrimeTable.Cols.TITLE + ", " +
CrimeTable.Cols.DATE + ", " +
CrimeTable.Cols.SOLVED +", " +
CrimeTable.Cols.SUSPECT +
")"
);
}
3.写入数据库
创建ContentValues
private static ContentValues getContentValues(Crime crime){
ContentValues values = new ContentValues();
values.put(CrimeTable.Cols.UUID,crime.getId().toString());
values.put(CrimeTable.Cols.TITLE,crime.getTitle());
values.put(CrimeTable.Cols.DATE,crime.getDate().getTime());
values.put(CrimeTable.Cols.SOLVED,crime.isSolved()?1:0);
values.put(CrimeTable.Cols.SUSPECT,crime.getSuspect());
return values;
}
插入记录
public void addCrime(Crime c){
ContentValues values = getContentValues(c);
mDatabase.insert(CrimeTable.NAME,null,values);
}
更新记录
public void updateCrime(Crime crime){
String uuidString = crime.getId().toString();
ContentValues values = getContentValues(crime);
mDatabase.update(CrimeTable.NAME,values,CrimeTable.Cols.UUID+"=?",
new String[]{uuidString});
}
Crime数据刷新
@Override
public void onPause(){
super.onPause();
CrimeLab.get(getActivity())
.updateCrime(mCrime);
}
4.读取数据库
创建CrimeCursorWrapper类
public class CrimeCursorWrapper extends CursorWrapper {
public CrimeCursorWrapper(Cursor cursor){
super(cursor);
}
}
新增getCrime()方法
public Crime getCrime(){
String uuidString = getString(getColumnIndex(CrimeDbSchema.CrimeTable.Cols.UUID));
String title = getString(getColumnIndex(CrimeDbSchema.CrimeTable.Cols.TITLE));
long date = getLong(getColumnIndex(CrimeDbSchema.CrimeTable.Cols.DATE));
int isSolved = getInt(getColumnIndex(CrimeDbSchema.CrimeTable.Cols.SOLVED));
return null;
}
新增Crime构造方法
public Crime(){
this(UUID.randomUUID());
// mId = UUID.randomUUID();
// mDate = new Date();
}
public Crime(UUID id){
mId = id;
mDate = new Date();
}
完成getCrime()方法
Crime crime = new Crime(UUID.fromString(uuidString));
crime.setTitle(title);
crime.setDate(new java.util.Date(date));
crime.setSolved(isSolved!=0);
crime.setSuspect(suspect);
return crime;
使用Cursor封装方法
//private Cursor queryCrimes(String whereClause,String[] whereArgs){
private CrimeCursorWrapper queryCrimes(String whereClause,String[] whereArgs){
//return cursor;
return new CrimeCursorWrapper(cursor);
返回crime列表
public List<Crime> getCrimes() {
// return mCrimes;
List<Crime> crimes = new ArrayList<>();
CrimeCursorWrapper cursor = queryCrimes(null,null);
try {
cursor.moveToFirst();
while (!cursor.isAfterLast()){
crimes.add(cursor.getCrime());
cursor.moveToNext();
}
}finally {
cursor.close();
}
//return new ArrayList<>();
return crimes;
}
重写getCrime(UUID)方法
public Crime getCrime(UUID id){
CrimeCursorWrapper cursor = queryCrimes(
CrimeTable.Cols.UUID+"=?",
new String[]{id.toString()}
);
try {
if (cursor.getCount() == 0){
return null;
}
cursor.moveToFirst();
return cursor.getCrime();
}finally {
cursor.close();
}
添加setCrimes(List
public void setCrimes(List<Crime> crimes){
mCrimes = crimes;
}
调用setCrime(List
mAdapter.setCrimes(crimes);
隐式intent
我们将使用隐式intent发送短消息给Crime嫌疑人。用户首先从某个联系人应用选取联系人,然后从短消息应用列表中选取目标应用发送消息
1.添加组件
添加按钮字符串
<string name="crime_suspect_text">Choose Suspect</string>
<string name="crime_report_text">Send Crime Report</string>
添加按钮组件
<Button
android:id="@+id/crime_suspect"
android:text="@string/crime_suspect_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/crime_report"
android:text="@string/crime_report_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
2.添加嫌疑人信息至模型层
添加mSuspect成员变量
private String mSuspect;
public String getSuspect() {
return mSuspect;
}
public void setSuspect(String suspect) {
mSuspect = suspect;
}
添加嫌疑人数据库字段
public static final String SUSPECT = "suspect";
CrimeTable.Cols.SUSPECT +
写嫌疑人信息
values.put(CrimeTable.Cols.SUSPECT,crime.getSuspect());
读取嫌疑人信息
String suspect = getString(getColumnIndex(CrimeDbSchema.CrimeTable.Cols.SUSPECT));
crime.setSuspect(suspect);
4.发送消息
发送消息
private Button mReportButton;
mReportButton = (Button) v.findViewById(R.id.crime_report);
mReportButton.setOnClickListener(new View.OnClickListener(){
public void onClick(View v){
Intent i = new Intent(Intent.ACTION_SEND);
i.setType("text/plain");
i.putExtra(Intent.EXTRA_TEXT,getCrimeReport());
i.putExtra(Intent.EXTRA_SUBJECT,
getString(R.string.crime_report_suspect));
startActivity(i);
}
});
使用选择器
i = Intent.createChooser(i,getString(R.string.send_report));
添加嫌疑人按钮成员变量
private static final int REQUEST_CONTACT = 1;
private Button mSuspectButton;
发送隐式intent
final Intent pickContact = new Intent(Intent.ACTION_PICK,
ContactsContract.Contacts.CONTENT_URI);
mSuspectButton = (Button) v.findViewById(R.id.crime_suspect);
mSuspectButton.setOnClickListener(new View.OnClickListener(){
public void onClick(View v){
startActivityForResult(pickContact, REQUEST_CONTACT);
}
});
if (mCrime.getSuspect() != null){
mSuspectButton.setText(mCrime.getSuspect());
}
获取联系人姓名
if (requestCode == REQUEST_DATE){
Date date = (Date) data
.getSerializableExtra(DatePickerFragment.EXTRA_DATE);
mCrime.setDate(date);
updateDate();
}else if (requestCode == REQUEST_CONTACT && data != null){
Uri contactUri = data.getData();
//Specify which fields you want your query to return
//values for.
String[] queryFields = new String[]{
ContactsContract.Contacts.DISPLAY_NAME
};
//Perform your query - the contactUri is like a "where"
//clause here
Cursor c = getActivity().getContentResolver()
.query(contactUri,queryFields,null,null,null);
try {
//Double-check that you actually got results
if (c.getCount() == 0){
return;
}
//Pull out the first column of the first row of data -
//that is your suspect's name
c.moveToFirst();
String suspect = c.getString(0);
mCrime.setSuspect(suspect);
mSuspectButton.setText(suspect);
}finally {
c.close();
}
检查是否存在联系人应用
PackageManager packageManager = getActivity().getPackageManager();
if (packageManager.resolveActivity(pickContact,
PackageManager.MATCH_DEFAULT_ONLY) == null){
mSuspectButton.setEnabled(false);
}