Day07 心得與Update/搜尋功能實作


第七天
今日目標:

  1. update功能實作(下)
  2. 搜尋功能實作
  3. 心得感想

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();
    }
}
  1. 搜尋實作

跟之前一樣記得在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) {

    }
});}
  1. 心得跟改進方向
    第一次參加這樣的活動,這個節奏真的很緊湊,也看到很多真的很厲害的神人寫的文章,感覺受益良多
    不過因為平時上課 + 做專案的關係導致時間真的有點不夠,這次主要目標是要讓沒接觸過的人也看得懂,可是好像不小心就很容易越寫越難
    像這次的架構真的蠻亂的,要是我在寫or修改一次肯定會用mvp做

改進方向的部分大概有幾點

  1. 應該使用mvp/mvvm架構
  2. 時間不夠,不然應該會自己架個後端平台
  3. 變數取名的蠻爛的,好像有點容易搞混

如果你是想繼續學更深的話,有幾個方向可以建議

  1. retrofit
  2. Rxjava
  3. MVVM/MVP
  4. Room
  5. Dagger
    大概就這樣。。。應該算完賽成功 ..吧!!
#Android





初學者也能學會的超詳細介紹

留言討論