Android ile SQLite Veritabanı Kullanımı (Örnek Uygulama Anlatımı ile)

Android işletim sistemli cihazlarda, verileri kalıcı olarak saklamanın birkaç yolu vardır. SQLite, uygulama verilerini depolama yöntemlerinden birisidir. Android işletim sistemi ile birlikte gelen çok hafif bir veritabanıdır. Eğer uygulamanızda basit veri nesneleri depolaması gerekiyorsa SQLite sistemini kullanmaya çalışın. SQLite kullanımı size hız, performans ve modülerlik sağlayacaktır.

Bu makalede, Android işletim sistemli cihazlarda veritabanının temellerini SQLite kullanarak oluşturacağımız Notlarım uygulaması ile öğreneceğiz.

1. The Notlarım Uygulaması

Veri tabanı depolamasının Android uygulamalarda nasıl çalıştığını göstermek üzere basit bir Notlarım uygulaması oluşturacağız. Bu uygulama kullanıcının yeni not girebildiği, silebildiği veya güncelleme yapabildiği bir ekrandan oluşan basit bir uygulamadan oluşacaktır. Uygulama ile alakalı ekran görüntüleri şu şekildedir;


Hadi Android Studio'da notlarım uygulamasını oluşturmaya başlayalım.

2. Yeni Android Uygulama Oluşturulması

1. Android Studio'da File ⇒ New Project seçeneğini seçip, templates olarak görüntülenen seçeneklerden Basic Activity olanı seçerek yeni bir Android proje oluşturun.

2. app dizini altında bulunan build.gradle dosyasını açın ve RecyclerView kütüphanesini ekleyin. Bu kütüphane notların listelenmesinde kullanılacaktır.

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    // ..
 
    implementation 'com.android.support:recyclerview-v7:26.1.0'
}

3. colors.xml, dimens.xml ve strings.xml dosyalarına aşağıdaki kod parçalarını ekleyin.

<?xml version="1.0" encoding="utf-8"?> 
<resources> 
    <color name="colorPrimary">#455399</color> 
    <color name="colorPrimaryDark">#455399</color> 
    <color name="colorAccent">#00c6ae</color> 
    <color name="msg_no_notes">#999</color> 
    <color name="hint_enter_note">#89c3c3c3</color> 
    <color name="timestamp">#858585</color> 
    <color name="note_list_text">#232323</color> 
</resources>

<resources> 
    <dimen name="fab_margin">16dp</dimen> 
    <dimen name="activity_margin">16dp</dimen> 
    <dimen name="dot_margin_right">10dp</dimen> 
    <dimen name="msg_no_notes">26sp</dimen> 
    <dimen name="margin_top_no_notes">120dp</dimen> 
    <dimen name="lbl_new_note_title">20sp</dimen> 
    <dimen name="dimen_10">10dp</dimen> 
    <dimen name="input_new_note">20sp</dimen> 
    <dimen name="dot_height">30dp</dimen> 
    <dimen name="dot_text_size">40sp</dimen> 
    <dimen name="timestamp">14sp</dimen> 
    <dimen name="note_list_text">18sp</dimen> 
</resources>

<resources> 
   <string name="app_name">Notlarım</string> 
   <string name="action_settings">Ayarlar</string> 
   <string name="activity_title_home">Notlar</string> 
   <string name="msg_no_notes">Hernangi bir not bulunamadı!</string> 
   <string name="lbl_new_note_title">Yeni Not</string> 
   <string name="lbl_edit_note_title">Notu Güncelle</string> 
   <string name="hint_enter_note">Notunu gir!</string> 
</resources>

4. Projede database, database/model, utils ve view isimlerinde dosya paketleri oluşturun. Yapılan düzenlemelerden son projenin son hali şu şekilde olacaktır;

2.1. SQLite Helper Sınıfının Oluşturulması

Android'in official kütüphanesi olan SQLiteOpenHelper sınıfı miras alınarak yeni bir sınıf oluşturalım. Bu sınıf CRUD(Create, Read, Update, Delete) yani notlarımız için gerekli olan ekleme, okuma, güncelleme ve silme işlemlerini kapsayacak şekilde ayarlanacaktır.

Veritabanına kayıt edilen notları daha kolay yönetebilmek için Notes modelini oluşturalım.

5. database/model paketi altında, Note.java sınıfı oluşturun. Bu sınıf içerisinde tablo ismi, sütunlar, bu tabloya ait SQL sorgularını ve getter/setter metodlarını içermektir.

  • `notes` tablosu `id`, `note` and `timestamp` gibi sütunları içermektedir.
  • `id` sütunu eklenen notların tekil olmasını sağlamada kullanılan alandır.
  • `note` sütunu yazılan notların tutulduğu alandır.
  • `timestamp` sütunu eklenen notların kayıt tarihini tutmada kullanılan alandır.

public class Note {
    public static final String TABLE_NAME = "notes";
 
    public static final String COLUMN_ID = "id";
    public static final String COLUMN_NOTE = "note";
    public static final String COLUMN_TIMESTAMP = "timestamp";
 
    private int id;
    private String note;
    private String timestamp;
 
 
    // Create table SQL query
    public static final String CREATE_TABLE =
            "CREATE TABLE " + TABLE_NAME + "("
                    + COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
                    + COLUMN_NOTE + " TEXT,"
                    + COLUMN_TIMESTAMP + " DATETIME DEFAULT CURRENT_TIMESTAMP"
                    + ")";
 
    public Note() {
    }
 
    public Note(int id, String note, String timestamp) {
        this.id = id;
        this.note = note;
        this.timestamp = timestamp;
    }
 
    public int getId() {
        return id;
    }
 
    public String getNote() {
        return note;
    }
 
    public void setNote(String note) {
        this.note = note;
    }
 
    public String getTimestamp() {
        return timestamp;
    }
 
    public void setId(int id) {
        this.id = id;
    }
 
    public void setTimestamp(String timestamp) {
        this.timestamp = timestamp;
    }
}

6. database paketi altında, DatabaseHelper.java adında ve SQLiteOpenHelper sınıfını miras alan bir sınıf oluşturun. Bu sınıf veritabanı için yapılacak tüm işlemlerde kullanılacaktır.

  • onCreate() fonksiyonu uygulama yüklendiğinde sadece bir kere çağrılmaktadır. Bu metod, uygulamada kullanılacak veritabanı ve bu veritabanında kullanılacak olan tabloların oluşturulmasında kullanılmaktadır.
  • Tablolarda herhangi bir güncelleme gerektiğinde onUpgrade() fonksiyonu kullanılmaktadır. Herhangi bir güncelleme olup olmadığını DATABASE_VERSION numarasına göre gerçekleştirebilirsiniz. Tabloda herhangi bir yeni sütun eklenmesi veya yeni tabloların oluşturulması durumunda bu numaranın yükseltilmesi yeterli olacaktır. Örneğimizde mevcut olan tabloların tümünün silinmesi ve yeniden oluşturulması sağlanmıştır.

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
 
import java.util.ArrayList;
import java.util.List;
 
import info.yazilimdersi.sqlite.database.model.Note;
 
public class DatabaseHelper extends SQLiteOpenHelper {
 
    // Veritabanı versiyonu
    private static final int DATABASE_VERSION = 1;
 
    // Veritabanı adı
    private static final String DATABASE_NAME = "notes_db";
 
 
    public DatabaseHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }
 
    // Tabloların oluşturulması
    @Override
    public void onCreate(SQLiteDatabase db) {
 
        // notes tablosunu oluştur
        db.execSQL(Note.CREATE_TABLE);
    }
 
    // Veritabanının güncellenmesi
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // Mevcut notes tablosunu kaldır.
        db.execSQL("DROP TABLE IF EXISTS " + Note.TABLE_NAME);
 
        // Veritabanını tekrardan oluştur.
        onCreate(db);
    }
}

Artık notları kayıt etmede kullanılacak olan veritabanı oluşturuldu. Şimdi aynı sınıfa aşağıdaki fonksiyonları ekleyelim;

a. Not Eklenmesi

Bu fonksiyon veritabanına yazma imkanı sunan getWritableDatabase() metoduna erişim gerektirmektedir. Aşağıdaki kodlamada veritabanına yeni bir notun nasıl kayıt edildiğini görebilirsiniz;

  • ContentValues() sütun isimlerinin belirlenmesi ve verilerin kayıt edilmesinde kullanılmaktadır. Burada, `id` and `timestamp` sütunları otomatik olarak setleneceği için bunları ekleme işleminde tanımlamıyoruz.
  • Her zaman veritabanında yapılacak işlemin bitirilmesinin ardından db.close() metodunun çağrılması gerekmektedir. db.close() metodunun çağrılması aktif olan bağlantının kapatılmasını sağlamaktadır.
  • Herhangi bir yeni kayıt oluşturulduğunda eklenen kayda ait `id` verisi dönecektir.

public long insertNote(String note) {
    // veritabanına erişimde kullanılacak nesne
    SQLiteDatabase db = this.getWritableDatabase();
 
    ContentValues values = new ContentValues();
    // `id` and `timestamp` otomatik oluşturulduğu için eklemeye gerek yoktur.
    values.put(Note.COLUMN_NOTE, note);
 
    // yeni kayıt oluştur
    long id = db.insert(Note.TABLE_NAME, null, values);
 
    // bağlantıyı kapat
    db.close();
 
    // yeni eklenen kaydın id bilgisini dönebilirsin.
    return id;
}

b. Notların Listelenmesi

Bu fonksiyon veritabanına okuma imkanı sunan getReadableDatabase() metoduna erişim gerektirmektedir. Aşağıdaki kodlamada veritabanında kayıtlı olan tüm notların ve sadece istenilen nota erişimi görebilirsiniz;

  • getNote() metodu ile iletilen `id` parametresine bağlı olarak ilişkili notun döndürülmesi sağlanmıştır.
  • getAllNotes() metodunun çağrılması ile veritabanında kayıtlı tüm notların getirilmesi sağlanmıştır.
  • getNotesCount() metodu ile veritabanında kayıtlı bulunan notların sayısını dönmektedir.


public Note getNote(long id) {
    SQLiteDatabase db = this.getReadableDatabase();
 
    Cursor cursor = db.query(Note.TABLE_NAME,
            new String[]{Note.COLUMN_ID, Note.COLUMN_NOTE, Note.COLUMN_TIMESTAMP},
            Note.COLUMN_ID + "=?",
            new String[]{String.valueOf(id)}, null, null, null, null);
 
    if (cursor != null)
        cursor.moveToFirst();
 
    Note note = new Note(
            cursor.getInt(cursor.getColumnIndex(Note.COLUMN_ID)),
            cursor.getString(cursor.getColumnIndex(Note.COLUMN_NOTE)),
            cursor.getString(cursor.getColumnIndex(Note.COLUMN_TIMESTAMP)));
 
    // veritabanı bağlantısını kapatalım
    cursor.close();
 
    return note;
}
 
public List getAllNotes() {
    List notes = new ArrayList<>();
 
    // Select Sorgusu
    String selectQuery = "SELECT  * FROM " + Note.TABLE_NAME + " ORDER BY " +
            Note.COLUMN_TIMESTAMP + " DESC";
 
    SQLiteDatabase db = this.getWritableDatabase();
    Cursor cursor = db.rawQuery(selectQuery, null);
 
    if (cursor.moveToFirst()) {
        do {
            Note note = new Note();
            note.setId(cursor.getInt(cursor.getColumnIndex(Note.COLUMN_ID)));
            note.setNote(cursor.getString(cursor.getColumnIndex(Note.COLUMN_NOTE)));
            note.setTimestamp(cursor.getString(cursor.getColumnIndex(Note.COLUMN_TIMESTAMP)));
 
            notes.add(note);
        } while (cursor.moveToNext());
    }
 
    // veritabanı bağlantısını kapatalım
    db.close();
 
    // notların tümünü döner
    return notes;
}
 
public int getNotesCount() {
    String countQuery = "SELECT  * FROM " + Note.TABLE_NAME;
    SQLiteDatabase db = this.getReadableDatabase();
    Cursor cursor = db.rawQuery(countQuery, null);
 
    int count = cursor.getCount();
    cursor.close();
 
 
    // notların sayısını döner
    return count;
}

c. Notun Güncellenmesi

Bu fonksiyon veritabanına yazma imkanı sunan getWritableDatabase() metoduna erişim gerektirmektedir. Aşağıdaki kodlamada veritabanında kayıtlı bir notun nasıl güncellenebildiğini görebilirsiniz;


public int updateNote(Note note) {
    SQLiteDatabase db = this.getWritableDatabase();
 
    ContentValues values = new ContentValues();
    values.put(Note.COLUMN_NOTE, note.getNote());
 
    // notunu güncelleyelim
    return db.update(Note.TABLE_NAME, values, Note.COLUMN_ID + " = ?",
            new String[]{String.valueOf(note.getId())});
}

c. Notun Silinmesi

Bu fonksiyon veritabanına yazma imkanı sunan getWritableDatabase() metoduna erişim gerektirmektedir. Aşağıdaki kodlamada veritabanında kayıtlı bir notun nasıl silindiğini görebilirsiniz;


public void deleteNote(Note note) {
    SQLiteDatabase db = this.getWritableDatabase();
    db.delete(Note.TABLE_NAME, Note.COLUMN_ID + " = ?",
            new String[]{String.valueOf(note.getId())});
    db.close();
}

7. utils paketi altında, RecyclerTouchListener.java ve MyDividerItemDecoration.java adında sınıflar oluşturun.

  • RecyclerTouchListener sınıfı ile listelemede tıklanan alan ile alakalı alınacak aksiyonlar tanımlanır.
  • MyDividerItemDecoration sınıfı ile listeler arasına çizilmesi istenen çizgilerin oluşturulmasında kullanılmaktadır.


import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
 
public class RecyclerTouchListener implements RecyclerView.OnItemTouchListener {
 
    private ClickListener clicklistener;
    private GestureDetector gestureDetector;
 
    public RecyclerTouchListener(Context context, final RecyclerView recycleView, final ClickListener clicklistener) {
 
        this.clicklistener = clicklistener;
        gestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
            @Override
            public boolean onSingleTapUp(MotionEvent e) {
                return true;
            }
 
            @Override
            public void onLongPress(MotionEvent e) {
                View child = recycleView.findChildViewUnder(e.getX(), e.getY());
                if (child != null && clicklistener != null) {
                    clicklistener.onLongClick(child, recycleView.getChildAdapterPosition(child));
                }
            }
        });
    }
 
    @Override
    public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
        View child = rv.findChildViewUnder(e.getX(), e.getY());
        if (child != null && clicklistener != null && gestureDetector.onTouchEvent(e)) {
            clicklistener.onClick(child, rv.getChildAdapterPosition(child));
        }
 
        return false;
    }
 
    @Override
    public void onTouchEvent(RecyclerView rv, MotionEvent e) {
 
    }
 
    @Override
    public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
 
    }
 
    public interface ClickListener {
        void onClick(View view, int position);
 
        void onLongClick(View view, int position);
    }
}


import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.TypedValue;
import android.view.View;
 
public class MyDividerItemDecoration extends RecyclerView.ItemDecoration {
 
    private static final int[] ATTRS = new int[]{
            android.R.attr.listDivider
    };
 
    public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;
    public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;
 
    private Drawable mDivider;
    private int mOrientation;
    private Context context;
    private int margin;
 
    public MyDividerItemDecoration(Context context, int orientation, int margin) {
        this.context = context;
        this.margin = margin;
        final TypedArray a = context.obtainStyledAttributes(ATTRS);
        mDivider = a.getDrawable(0);
        a.recycle();
        setOrientation(orientation);
    }
 
    public void setOrientation(int orientation) {
        if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) {
            throw new IllegalArgumentException("invalid orientation");
        }
        mOrientation = orientation;
    }
 
    @Override
    public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
        if (mOrientation == VERTICAL_LIST) {
            drawVertical(c, parent);
        } else {
            drawHorizontal(c, parent);
        }
    }
 
    public void drawVertical(Canvas c, RecyclerView parent) {
        final int left = parent.getPaddingLeft();
        final int right = parent.getWidth() - parent.getPaddingRight();
 
        final int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++) {
            final View child = parent.getChildAt(i);
            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
                    .getLayoutParams();
            final int top = child.getBottom() + params.bottomMargin;
            final int bottom = top + mDivider.getIntrinsicHeight();
            mDivider.setBounds(left + dpToPx(margin), top, right - dpToPx(margin), bottom);
            mDivider.draw(c);
        }
    }
 
    public void drawHorizontal(Canvas c, RecyclerView parent) {
        final int top = parent.getPaddingTop();
        final int bottom = parent.getHeight() - parent.getPaddingBottom();
 
        final int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++) {
            final View child = parent.getChildAt(i);
            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
                    .getLayoutParams();
            final int left = child.getRight() + params.rightMargin;
            final int right = left + mDivider.getIntrinsicHeight();
            mDivider.setBounds(left, top + dpToPx(margin), right, bottom - dpToPx(margin));
            mDivider.draw(c);
        }
    }
 
    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        if (mOrientation == VERTICAL_LIST) {
            outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
        } else {
            outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
        }
    }
 
    private int dpToPx(int dp) {
        Resources r = context.getResources();
        return Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, r.getDisplayMetrics()));
    }
}

1. Notlarım Uygulamasının Arayüzünün Tasarlanması

Veritabanı ile alakalı işlemler gerçekleştirildi. Şimdi sıra uygulamanın arayüzünün oluşturulması ve bunun veritabanı ile ilişkilendirilmesinde;

Öncelikle notlarımız listelendiği bir layout sayfasına ve bununla ilişkili adapter sınıfına ihtiyacımız bulunmakta.

9. Her notun tek başına görüntülenebildiği arayüzü oluşturmak için note_list_row.xml adında bir layout oluşturun.


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:clickable="true"
    android:foreground="?attr/selectableItemBackground"
    android:paddingBottom="@dimen/dimen_10"
    android:paddingLeft="@dimen/activity_margin"
    android:paddingRight="@dimen/activity_margin"
    android:paddingTop="@dimen/dimen_10">
 
    <TextView
        android:id="@+id/dot"
        android:layout_width="wrap_content"
        android:layout_height="@dimen/dot_height"
        android:layout_marginRight="@dimen/dot_margin_right"
        android:layout_marginTop="@dimen/dimen_10"
        android:includeFontPadding="false"
        android:textColor="@color/colorAccent"
        android:lineSpacingExtra="0dp"
        android:textSize="@dimen/dot_text_size" />
 
    <TextView
        android:id="@+id/timestamp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/dot"
        android:textColor="@color/timestamp"
        android:textSize="@dimen/timestamp" />
 
    <TextView
        android:id="@+id/note"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/timestamp"
        android:layout_toRightOf="@id/dot"
        android:textColor="@color/note_list_text"
        android:textSize="@dimen/note_list_text" />
 
</RelativeLayout>


10. view paketi altında, NotesAdapter.java adında bir sınıf oluşturalım. Bu adapter arayüz ile alakalı yapılması planlanan gösterimlerde kullanılacaktır. Ayrıca listelemede tıklanan notun hangisi olduğunu belirlemeye de yaramaktadır.

 

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
 
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
 
import info.androidhive.sqlite.R;
import info.androidhive.sqlite.database.model.Note;
 
public class NotesAdapter extends RecyclerView.Adapter {
 
    private Context context;
    private List notesList;
 
    public class MyViewHolder extends RecyclerView.ViewHolder {
        public TextView note;
        public TextView dot;
        public TextView timestamp;
 
        public MyViewHolder(View view) {
            super(view);
            note = view.findViewById(R.id.note);
            dot = view.findViewById(R.id.dot);
            timestamp = view.findViewById(R.id.timestamp);
        }
    }
 
 
    public NotesAdapter(Context context, List notesList) {
        this.context = context;
        this.notesList = notesList;
    }
 
    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.note_list_row, parent, false);
 
        return new MyViewHolder(itemView);
    }
 
    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        Note note = notesList.get(position);
 
        holder.note.setText(note.getNote());
 
        // Her notun başında nokta simgesinin gösterimi
        holder.dot.setText(Html.fromHtml("•"));
 
        // Oluşturulduğu zaman diliminin formatlanması ve görüntülenmesi
        holder.timestamp.setText(formatDate(note.getTimestamp()));
    }
 
    @Override
    public int getItemCount() {
        return notesList.size();
    }
 
    private String formatDate(String dateStr) {
        try {
            SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date date = fmt.parse(dateStr);
            SimpleDateFormat fmtOut = new SimpleDateFormat("MMM d");
            return fmtOut.format(date);
        } catch (ParseException e) {
 
        }
 
        return "";
    }
}


3.1 Yeni Not Ekleme/Güncellemede Kullanılacak Dialogların Oluşturulması

Oluşturulacak dialogda sadece not girilmesi veya notun editlenebilmesi gibi özellik içerdiğinden EditText elementinin layouta eklenmesi yeterli olacaktır. Burada daha hızlı aksiyon almak adına direkt olarak Dialog elementini kullanabiliriz.

10. Yeni not girmede kullanılacak olan note_dialog.xml adında bir layout oluşturun.

 

 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingLeft="@dimen/activity_margin"
    android:paddingRight="@dimen/activity_margin"
    android:paddingTop="@dimen/activity_margin">
 
    <TextView android:id="@+id/dialog_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="@dimen/dimen_10"
        android:fontFamily="sans-serif-medium"
        android:lineSpacingExtra="8sp"
        android:text="@string/lbl_new_note_title"
        android:textColor="@color/colorAccent"
        android:textSize="@dimen/lbl_new_note_title"
        android:textStyle="normal" />
 
    <EditText
        android:id="@+id/note"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@android:color/transparent"
        android:gravity="top"
        android:hint="@string/hint_enter_note"
        android:inputType="textCapSentences|textMultiLine"
        android:lines="4"
        android:textColorHint="@color/hint_enter_note"
        android:textSize="@dimen/input_new_note" />
 
</LinearLayout>


11. activity_main.xml ve content_main.xml dosyalarını açın ve içerisine RecyclerView widgetini ekleyin.

 
 
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/coordinator_layout"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="info.androidhive.sqlite.view.MainActivity">
 
    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">
 
        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/AppTheme.PopupOverlay" />
 
    </android.support.design.widget.AppBarLayout>
 
    <include layout="@layout/content_main" />
 
    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:layout_margin="@dimen/fab_margin"
        app:srcCompat="@drawable/ic_add_white_24dp" />
 
</android.support.design.widget.CoordinatorLayout>



<RelativeLayout 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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context="info.androidhive.sqlite.view.MainActivity"
    tools:showIn="@layout/activity_main">
 
    <android.support.v7.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
 
    <TextView
        android:id="@+id/empty_notes_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="@dimen/margin_top_no_notes"
        android:fontFamily="sans-serif-light"
        android:text="@string/msg_no_notes"
        android:textColor="@color/msg_no_notes"
        android:textSize="@dimen/msg_no_notes" />
 
</RelativeLayout>


12. Son olarak MainActivity.java sınıfını açıp aşağıdaki düzenlemeleri yapın;

  • showNoteDialog() metodu yeni bir not girilmesi için dialog açmaktadır.
  • createNote() veritabanına yeni kayıt eklenmesi ve eklenen yeni kaydın notların listelendiği arayüzde gözükmesini sağlamaktadır.
  • showActionsDialog() fonksiyonu `Güncelle` ve `Sil` seçeneklerinin görüntülenmesini sağlamaktadır. Bu arayüze ulaşmak için listelemede bulunan notlardan herhangi birisine uzun süre basılı tutmanız gerekmektedir.
  • Güncelle seçeneğine tıklanıldığında, tıklanılan notun text kısmı dialog içerisinde editlenecek şekilde görüntülenmektedir. updateNote() metodu çağrılarak, mevcut kaydın veritabanında güncellenmesi ve arayüze yansıması sağlanmaktadır.
  • deleteNote() metodu veritabanında ilgili notun silinmesini sağlamaktadır. Listelemede görüntülenen kaydın silinmesi için adaptere ait notifyItemRemoved() metodunun çağrılması gerekmektedir.
  • toggleEmptyNotes() metodu ise notların sayısına bağlı olarak eğer herhangi bir not bulunmuyorsa ona göre farklı bir arayüz gösterimine gidilmesini sağlamaktadır.


import android.content.DialogInterface;
import android.os.Bundle;
import android.support.design.widget.CoordinatorLayout;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
 
import java.util.ArrayList;
import java.util.List;
 
import info.androidhive.sqlite.R;
import info.androidhive.sqlite.database.DatabaseHelper;
import info.androidhive.sqlite.database.model.Note;
import info.androidhive.sqlite.utils.MyDividerItemDecoration;
import info.androidhive.sqlite.utils.RecyclerTouchListener;
 
public class MainActivity extends AppCompatActivity {
    private NotesAdapter mAdapter;
    private List notesList = new ArrayList<>();
    private CoordinatorLayout coordinatorLayout;
    private RecyclerView recyclerView;
    private TextView noNotesView;
 
    private DatabaseHelper db;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
 
        coordinatorLayout = findViewById(R.id.coordinator_layout);
        recyclerView = findViewById(R.id.recycler_view);
        noNotesView = findViewById(R.id.empty_notes_view);
 
        db = new DatabaseHelper(this);
 
        notesList.addAll(db.getAllNotes());
 
        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                showNoteDialog(false, null, -1);
            }
        });
 
        mAdapter = new NotesAdapter(this, notesList);
        RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
        recyclerView.setLayoutManager(mLayoutManager);
        recyclerView.setItemAnimator(new DefaultItemAnimator());
        recyclerView.addItemDecoration(new MyDividerItemDecoration(this, LinearLayoutManager.VERTICAL, 16));
        recyclerView.setAdapter(mAdapter);
 
        toggleEmptyNotes();
 
        
        recyclerView.addOnItemTouchListener(new RecyclerTouchListener(this,
                recyclerView, new RecyclerTouchListener.ClickListener() {
            @Override
            public void onClick(View view, final int position) {
            }
 
            @Override
            public void onLongClick(View view, int position) {
                showActionsDialog(position);
            }
        }));
    }
 
    private void createNote(String note) {
        // yeni not ekleyin
        long id = db.insertNote(note);
 
        // veritabanına eklenen yeni notun id bilgisini alın.
        Note n = db.getNote(id);
 
        if (n != null) {
            // listeye yeni not ekleyin
            notesList.add(0, n);
 
            // listelemeyi güncelleyin
            mAdapter.notifyDataSetChanged();
 
            toggleEmptyNotes();
        }
    }
 
    private void updateNote(String note, int position) {
        Note n = notesList.get(position);
        // notun text kısmını setleyin
        n.setNote(note);
 
        // notu veritabanında güncelleyin
        db.updateNote(n);
 
        // listeyi güncelleyin
        notesList.set(position, n);
        mAdapter.notifyItemChanged(position);
 
        toggleEmptyNotes();
    }
 
    private void deleteNote(int position) {
        // veritabanından notu silin
        db.deleteNote(notesList.get(position));
 
        // listeden notu kaldırın
        notesList.remove(position);
        mAdapter.notifyItemRemoved(position);
 
        toggleEmptyNotes();
    }
 
    private void showActionsDialog(final int position) {
        CharSequence colors[] = new CharSequence[]{"Güncelle", "Sil"};
 
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("Seçeneği seçin");
        builder.setItems(colors, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                if (which == 0) {
                    showNoteDialog(true, notesList.get(position), position);
                } else {
                    deleteNote(position);
                }
            }
        });
        builder.show();
    }
  
    private void showNoteDialog(final boolean shouldUpdate, final Note note, final int position) {
        LayoutInflater layoutInflaterAndroid = LayoutInflater.from(getApplicationContext());
        View view = layoutInflaterAndroid.inflate(R.layout.note_dialog, null);
 
        AlertDialog.Builder alertDialogBuilderUserInput = new AlertDialog.Builder(MainActivity.this);
        alertDialogBuilderUserInput.setView(view);
 
        final EditText inputNote = view.findViewById(R.id.note);
        TextView dialogTitle = view.findViewById(R.id.dialog_title);
        dialogTitle.setText(!shouldUpdate ? getString(R.string.lbl_new_note_title) : getString(R.string.lbl_edit_note_title));
 
        if (shouldUpdate && note != null) {
            inputNote.setText(note.getNote());
        }
        alertDialogBuilderUserInput
                .setCancelable(false)
                .setPositiveButton(shouldUpdate ? "güncelle" : "kaydet", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialogBox, int id) {
 
                    }
                })
                .setNegativeButton("iptal",
                        new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialogBox, int id) {
                                dialogBox.cancel();
                            }
                        });
 
        final AlertDialog alertDialog = alertDialogBuilderUserInput.create();
        alertDialog.show();
 
        alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // Herhangi bir not girilmediğinde hata mesajının gösterilmesi
                if (TextUtils.isEmpty(inputNote.getText().toString())) {
                    Toast.makeText(MainActivity.this, "Not Girin!", Toast.LENGTH_SHORT).show();
                    return;
                } else {
                    alertDialog.dismiss();
                }
 
                // eğer kullanıcı notlarda güncelleme yapıyorsa
                if (shouldUpdate && note != null) {
                    // kayıtlı notu id verisi ile güncellemek
                    updateNote(inputNote.getText().toString(), position);
                } else {
                    // yeni not oluşturma
                    createNote(inputNote.getText().toString());
                }
            }
        });
    }
 
    /**
     * Eğer kayıtlı not bulunmuyorsa layout değişikliğinin sağlanması
     */
    private void toggleEmptyNotes() {
 
        if (db.getNotesCount() > 0) {
            noNotesView.setVisibility(View.GONE);
        } else {
            noNotesView.setVisibility(View.VISIBLE);
        }
    }
}


Böylelikle SQLite kullanarak Android uygulamada basit bir not uygulaması hazırlanmış oldu.
comments powered by Disqus