第七天
今日目標:
- update功能實作(下)
- 搜尋功能實作
- 心得感想
1.1 建立EditActivity 和 xml 介面
右鍵 -> new Activity->命名為EditActivity
Xml架構和之前差不多,唯一差異是我們這次要把資料都綁定上去
因為之前在AddActivity的部分有把資料傳到EditActivity所以可以直接綁定
然後資料型態都是Todo 所以在variable data的地方要將todo宣告成data!
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="data"
type="com.example.alarmmanagerproject.model.Todo" />
<variable
name="view"
type="com.example.alarmmanagerproject.edit.EditContract.View" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".edit.EditActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:layout_marginTop="30dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0px"
android:layout_weight="0.5"
android:background="@drawable/item"
android:orientation="horizontal"
android:layout_marginBottom="20dp">
<EditText
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:hint="標題"
android:text="@{data.title}"
android:background="@null"
android:layout_marginLeft="10dp"
android:layout_weight="2" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0px"
android:layout_weight="3"
android:background="@drawable/item"
android:orientation="horizontal"
android:layout_marginBottom="20dp">
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3"
android:layout_marginTop="10dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:background="@drawable/item"
android:orientation="horizontal">
<EditText
android:id="@+id/discription"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="@null"
android:hint="內文"
android:text="@{data.desc}"
android:gravity="left|top"
android:layout_weight="2" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0px"
android:layout_weight="0.5"
android:layout_marginBottom="20dp"
android:orientation="horizontal">
<TextView
android:id="@+id/date_picker"
android:layout_width="0px"
android:layout_height="match_parent"
android:hint="日期"
android:text="@{data.date}"
android:onClick="@{()->view.onDateClick()}"
android:background="@drawable/item"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:gravity="center"
android:layout_weight="1" />
<TextView
android:id="@+id/time_picker"
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_weight="1"
android:background="@drawable/item"
android:gravity="center"
android:hint="時間"
android:text="@{data.clock}"
android:onClick="@{()->view.onTimeClick()}" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0px"
android:layout_weight="0.35"
android:orientation="horizontal"
android:layout_marginBottom="20dp"
android:background="@drawable/item"
android:gravity="center">
<CheckBox
android:id="@+id/setTimercheck"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:layout_weight="1"
android:text="是否設置定時提醒"
/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.5"
android:orientation="horizontal"
android:layout_marginBottom="20dp">
<FrameLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_gravity="center"
android:weightSum="3">
<Button
style="?android:attr/buttonBarButtonStyle"
android:textColor="@android:color/primary_text_light"
android:id="@+id/buttonP1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#FFCCCC"
android:text="high"
android:layout_weight="1"
android:onClick="onPrioritySelected" />
<Button
style="?android:attr/buttonBarButtonStyle"
android:textColor="@android:color/primary_text_light"
android:id="@+id/buttonP2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#FFEE99"
android:text="medium"
android:layout_weight="1"
android:onClick="onPrioritySelected" />
<Button
style="?android:attr/buttonBarButtonStyle"
android:textColor="@android:color/primary_text_light"
android:id="@+id/buttonP3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#AAFFEE"
android:text="low"
android:layout_weight="1"
android:onClick="onPrioritySelected" />
</LinearLayout>
<!-- RadioGroup for visible selection of a priority -->
<RadioGroup
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_gravity="center"
android:weightSum="3">
<RadioButton
android:id="@+id/radButton1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="@{()->view.onPrioritySelected()}"
android:layout_weight="1" />
<RadioButton
android:id="@+id/radButton2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="@{()->view.onPrioritySelected()}"
android:layout_weight="1" />
<RadioButton
android:id="@+id/radButton3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="@{()->view.onPrioritySelected()}"
android:layout_weight="1" />
</RadioGroup>
</FrameLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginBottom="20dp">
<Button
android:id="@+id/upDate"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:onClick="@{()->view.onSubmit()}"
android:text="Update"
android:textColor="#FAFAFA"
android:textSize="22sp" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
1.2.0 記得創interface比較好用
public interface EditContract {
interface View {
void onTimeClick();
void onDateClick();
void onSubmit();
void onPrioritySelected();
}
}
1.2 EditActivity 主要內容
一開始也是一樣先init,比較特別的地方是這裡我們要接收從AddActivity傳過來的資料,記得用getStringExtra(“辨識參數”)接收。
/注意 記得傳過去的資料型態跟回傳的資料型態要一樣,不然有可能造成null/
For example
intent.putExtra("id", 1);
intent.getIntExtra(“id”);
在init的地方,上面我們在layout中用的是data綁定資料,所以這裡要將data set進去,所以用我們拿到傳過來的data值set進去
activityEditBinding.setData(todoData);
public void init() {
activityEditBinding = DataBindingUtil.setContentView(this, R.layout.activity_edit);
Todo todoData=new Todo(getIntent().getStringExtra("title"),getIntent().getStringExtra("date"),getIntent().getStringExtra("decs"),getIntent().getStringExtra("key"),getIntent().getStringExtra("clock"),0);
activityEditBinding.setData(todoData);
activityEditBinding.setView(this);
}
其餘的部分其實都跟AddActivity相差不多,所以我直接貼原始code上來
public class EditActivity extends AppCompatActivity implements EditContract.View,TimePickerDialog.OnTimeSetListener {
private DatabaseReference databaseReference;
private Integer mPriority;
private Calendar store;
private String key;
ActivityEditBinding activityEditBinding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_edit);
init();
}
public void init() {
activityEditBinding = DataBindingUtil.setContentView(this, R.layout.activity_edit);
Todo todoData=new Todo(getIntent().getStringExtra("title"),getIntent().getStringExtra("date"),getIntent().getStringExtra("decs"),getIntent().getStringExtra("key"),getIntent().getStringExtra("clock"),0);
activityEditBinding.setData(todoData);
activityEditBinding.setView(this);
}
@Override
public void onTimeClick() {
DialogFragment timePicker = new TimePickerFragment();
timePicker.show(getSupportFragmentManager(), "time picker");
}
@Override
public void onDateClick() {
final Calendar cm = Calendar.getInstance();
int mYear = cm.get(Calendar.YEAR);
int mMonth = cm.get(Calendar.MONTH);
int mDay = cm.get(Calendar.DAY_OF_MONTH);
DatePickerDialog datePickerDialog = new DatePickerDialog(this,
new DatePickerDialog.OnDateSetListener() {
@Override
public void onDateSet(DatePicker view, int year,
int monthOfYear, int dayOfMonth) {
activityEditBinding.datePicker.setText(dayOfMonth + "-" + (monthOfYear + 1) + "-" + year);
}
}, mYear, mMonth, mDay);
datePickerDialog.show();
}
public void onSubmit() {
if (activityEditBinding.setTimercheck.isChecked()) {
Log.d("test", "onSubmit: " + TextUtils.isEmpty(activityEditBinding.timePicker.getText()));
if (!TextUtils.isEmpty(activityEditBinding.timePicker.getText())) {
startAlarm(store);
}
} else {
cancelAlarm();
}
setDatabaseReference();
}
private void setDatabaseReference(){
key = getIntent().getStringExtra("key");
databaseReference = FirebaseDatabase.getInstance().getReference()
.child("Todo").child("Todo" + key);
databaseReference.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
dataSnapshot.getRef().child("priority").setValue(mPriority);
dataSnapshot.getRef().child("clock").setValue(activityEditBinding.timePicker.getText().toString());
dataSnapshot.getRef().child("keydoes").setValue(key);
dataSnapshot.getRef().child("title").setValue(activityEditBinding.title.getText().toString());
dataSnapshot.getRef().child("desc").setValue(activityEditBinding.discription.getText().toString());
dataSnapshot.getRef().child("date").setValue(activityEditBinding.datePicker.getText().toString());
Intent intent = new Intent(EditActivity.this, HomeActivity.class);
startActivity(intent);
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
}
public void onPrioritySelected() {
if ((activityEditBinding.radButton1).isChecked()) {
mPriority = 1;
} else if ((activityEditBinding.radButton2).isChecked()) {
mPriority = 2;
} else if ((activityEditBinding.radButton3).isChecked()) {
mPriority = 3;
}
}
@Override
public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
Calendar c = Calendar.getInstance();
c.set(Calendar.HOUR_OF_DAY, hourOfDay);
c.set(Calendar.MINUTE, minute);
c.set(Calendar.SECOND, 0);
store = Calendar.getInstance();
store = c;
updateTimeText(c);
}
private void updateTimeText(Calendar c) {
String timeText = DateFormat.getTimeInstance(DateFormat.SHORT).format(c.getTime());
activityEditBinding.timePicker.setText(timeText);
}
private void startAlarm(Calendar c) {
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, AlertReceiver.class);
int alarmId = SharedPreUtils.getInt(this, "alarm_id", 0);
SharedPreUtils.setInt(this, "alarm_id", ++alarmId);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, alarmId, intent, 0);
if (c.before(Calendar.getInstance())) {
c.add(Calendar.DATE, 1);
}
alarmManager.setExact(AlarmManager.RTC_WAKEUP, c.getTimeInMillis(), pendingIntent);
Toast.makeText(this, "您已設置定時提醒", Toast.LENGTH_SHORT).show();
}
private void cancelAlarm() {
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, AlertReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 1, intent, 0);
alarmManager.cancel(pendingIntent);
Toast.makeText(this, "您尚未設置定時提醒", Toast.LENGTH_SHORT).show();
}
}
- 搜尋實作
跟之前一樣記得在activity_home的地方加上
android:onClick="@{()->view.onSearchClick()}"
然後在HomeActivity的地方繼承,input是你拿輸入editText的值去丟進去
addValueListener,然後在判斷資料庫的資料是不是真的和你輸入的一樣,如果一樣的話就顯示,不一樣的話就會跳一個Toast出來並顯示空白。
@Override
public void onSearchClick() {
final String input = activityHomeBinding.editText.getText().toString();`
Log.d("777", "onClick: " + input);
mDatabase.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
todos.clear();
for (DataSnapshot singleSnapshot : dataSnapshot.getChildren()) {
String title = (String) singleSnapshot.child("title").getValue();
Log.d("777", "input: "+input);
Log.d("777", "title: "+title);
if (title.equals(input)) {
Todo p = singleSnapshot.getValue(Todo.class);
if (p.getTitle().equals(input)) {
todos.add(p);
}
Log.d("777", "onD: " + todos.get(0).getTitle());
}
Log.d("777", "onDataChange: "
+ title);
//do your logic
} else {
Toast.makeText(HomeActivity.this, "找不到資料QQ", Toast.LENGTH_SHORT).show();
}
homeAdapter = new HomeAdapter(todos,view);
ItemTouchHelper.Callback callback = new SimpleItemTouchHelperCallback(homeAdapter);
ItemTouchHelper touchHelper = new ItemTouchHelper(callback);
touchHelper.attachToRecyclerView(activityHomeBinding.recyclerview);
activityHomeBinding.recyclerview.setLayoutManager(new LinearLayoutManager(HomeActivity.this));
activityHomeBinding.recyclerview.setAdapter(homeAdapter);
homeAdapter.notifyDataSetChanged();
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});}
- 心得跟改進方向
第一次參加這樣的活動,這個節奏真的很緊湊,也看到很多真的很厲害的神人寫的文章,感覺受益良多
不過因為平時上課 + 做專案的關係導致時間真的有點不夠,這次主要目標是要讓沒接觸過的人也看得懂,可是好像不小心就很容易越寫越難
像這次的架構真的蠻亂的,要是我在寫or修改一次肯定會用mvp做
改進方向的部分大概有幾點
- 應該使用mvp/mvvm架構
- 時間不夠,不然應該會自己架個後端平台
- 變數取名的蠻爛的,好像有點容易搞混
如果你是想繼續學更深的話,有幾個方向可以建議
- retrofit
- Rxjava
- MVVM/MVP
- Room
- Dagger
大概就這樣。。。應該算完賽成功 ..吧!!