如何在Android中使用Realm数据库

我们都知道使用SQLite的本地数据库,它在Android 开发中用于内部存储器存储,主要存储本地数据,如联系人,电话详细信息等。现在我发现一个比SQLite更轻的数据库,被称为Realm数据库,我想我们可以彻底放弃SQLite了。

  1. 简单 -数据将以Object的形式存储在数据库中,因此可以方便地从数据库中检索数据。
  2. Fast - Realm数据库比SQLite数据库快于数据库的查询执行和维护。
  3. 跨平台 - 支持iOS和Android。。

一些注释

@PrimaryKey:此注释定义该字段设置为主键,且不能为空。
@Required:此注释可用于告诉Realm强制执行检查以禁止空值。
@Ignore:此注释用于不应该保留到磁盘的字段。
@Index:此注释将向该字段添加搜索索引。

注意

Realm主键是不支持自动增量的。您只能通过手动递增主键来突破此限制。也就是说每一次增加数据对象的时候,都必须为它添加一个主键值,这样才会产生新的数据,否则Realm数据库中的数据将会只有一条!!

比如在该实例中,我设置title为主键,那么每次添加数据都会setTitle()进一个值!

Realm数据库如何保存数据?

Realm数据库通过将Java对象直接保存到磁盘作为对象,而不是首先将它们映射到其他数据类型(如SQLite)来工作。在Realm数据库的中心,这个叫Realm的东西,这相当于一个传统的数据库。Realm可以将不同类型的对象映射到磁盘上的一个文件。另一种查看方式是,Realm是不需要从Java对象到磁盘上持久版本的单独映射的数据库。

它是一种像你所看到的是什么保存的工作流程 - 如果对象是Realm管理对象,则用户界面中对象的更改将自动保存到数据库。Realm管理的对象与SQLite表相当。要使Java对象成为Realm管理,该类必须扩展RealmObject或实现RealmModel接口。

我们来看看我们如何在我们的应用程序中实现Realm数据库。我们将要实现的效果如下图所示:

这里写图片描述

配置:将Realm库添加到您的项目中

在build.gradle(Project)文件中为Realm数据库添加依赖关系:

这里写图片描述

buildscript {
   repositories {
       jcenter()
   }
   dependencies {
       classpath 'com.android.tools.build:gradle:2.1.2'
       classpath 'io.realm:realm-gradle-plugin:1.1.1'
   }
}

allprojects {
   repositories {
       jcenter()
       maven { url "https://jitpack.io" }
   }
}

在打开您的应用程序级build.gradle(app)并应用Realm插件并安装一些库:

这里写图片描述

apply plugin: 'com.android.application'
apply plugin: 'realm-android'

// other stuff commented out for brevity

dependencies {
   compile fileTree(dir: 'libs', include: ['*.jar'])
   testCompile 'junit:junit:4.12'
   compile 'com.android.support:appcompat-v7:24.1.1'
   compile 'com.android.support:design:24.1.1'

   compile 'com.android.support:recyclerview-v7:24.1.1'
   compile 'com.github.thorbenprimke:realm-recyclerview:0.9.23'
}

这里我用了一个非常棒的名为RealmRecyclerView的库,它是一个用作数据存储的RecyclerView 包装器,并且支持下拉刷新和滑动删除,省去了很多工作。

用户界面

fragment_wanted_read_layout.xml:

<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <co.moonmonkeylabs.realmrecyclerview.RealmRecyclerView
        android:id="@+id/want_read_recycler"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:rrvIsRefreshable="false"
        app:rrvLayoutType="LinearLayout"
        app:rrvSwipeToDelete="true"
        app:rrvEmptyLayoutId="@layout/empty_view"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true">
        </co.moonmonkeylabs.realmrecyclerview.RealmRecyclerView>
</android.support.design.widget.CoordinatorLayout>

RecyclerView中的每个项目 都会单独显示,并且填充自己的布局。现在,我们应该创建布局以显示图书(Book)的项目,其中包含Book的名称,作者,页数和图像。我们通过 在app / res / layout中创建一个 名为note_item.xml的新资源文件来创建此布局,并将其内容替换为:

want_read_item_layout.xml

<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/card_books"
    style="@style/AppTheme.Card.Margins"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <ImageView
            android:id="@+id/image_background"
            android:layout_width="130dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical|start" />

        <LinearLayout
            android:id="@+id/layout_partner"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:paddingBottom="@dimen/margin_normal">

            <TextView
                android:id="@+id/text_books_title"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginBottom="@dimen/margin_small"
                android:paddingBottom="@dimen/margin_normal"
                android:paddingLeft="@dimen/margin_large"
                android:paddingRight="@dimen/margin_large"
                android:paddingTop="@dimen/margin_large"
                android:textSize="@dimen/text_size_large"
                android:textColor="#555555"
                android:maxLines="2"
                android:textStyle="bold"
                android:text="万历十五年"/>

            <TextView
                android:id="@+id/text_books_author"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:paddingLeft="@dimen/margin_large"
                android:paddingRight="@dimen/margin_large"
                android:textSize="@dimen/text_size_normal"
                android:textStyle="italic"
                android:text="黄宗仁"/>

            <TextView
                android:id="@+id/text_books_pages"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginBottom="@dimen/margin_small"
                android:paddingBottom="@dimen/margin_normal"
                android:paddingLeft="@dimen/margin_large"
                android:paddingRight="@dimen/margin_large"
                android:paddingTop="@dimen/margin_large"
                android:textSize="@dimen/text_size_normal"
                android:text="999页"/>

        </LinearLayout>
    </LinearLayout>
</android.support.v7.widget.CardView>

我想我们现在应该通过按下Run 按钮来确定一切都正常运行。

创建数据库表

没有像Realm数据库表这样的东西,但是我们有Realm管理的对象。使用短语“创建表”是因为这是我们熟悉的说法。所以为了创建表或自动更新对象,我们需要做的就是确保我们的模型类都从RealmObject基类扩展。而在我们这样做的时候,我们可以利用Realm的功能,如轻松处理关系,以便在我们的应用程序中定义一对多的关系,例如学生和注册账号之间的关系。一个学生可以有很多注册账号,但一个注册只能有一个这样的学生。
我们需要让我们将图书列表展示到我们的Activity/Fragment,这需要我们将图书信息存储到数据库中。但首先我们需要告诉我们的应用程序我们想要存储什么。

创建一个名为Book.java的新Java类。此类将包含我们的数据的属性以及Realm数据库表的主键如ID或者Title:

public class Book extends RealmObject{

    private int id;
    @PrimaryKey
    private String title;

    private String description;

    private String author;

    private String imageUrl;

    private String pages;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public String getImageUrl() {
        return imageUrl;
    }

    public void setImageUrl(String imageUrl) {
        this.imageUrl = imageUrl;
    }

    public String getPages() {
        return pages;
    }

    public void setPages(String pages) {
        this.pages = pages;
    }
}

管理Realm

我们最好把有关数据库的操作都放在一个类中进行管理,就像SQlite的帮助类一样:

RealmController .class

public class RealmController {
    private static String TAG = "RealmManager";
    private static RealmConfiguration realmConfiguration;
    private static Realm realm;

    public static Realm getSaveRealm() {
        return getRealm();
    }
    public static Realm getRealm() {
        try {
            if (realm == null) {
                realm = Realm.getDefaultInstance();
            }
        } catch (Exception e) {
            e.printStackTrace();
            Realm.deleteRealm(realmConfiguration);
            realm = Realm.getDefaultInstance();
        }
        return realm;
    }
    /**
     * 初始化Realm Configuration
     */
    public static void initializeRealmConfig(Context appContext) {
        if(realmConfiguration == null) {
            Log.d(TAG, "Initializing Realm configuration.");
            setRealmConfiguration(new RealmConfiguration.Builder(appContext).initialData(new RealmInitialData())
                    .deleteRealmIfMigrationNeeded()
                    .build());
        }
    }

/**
 * 设置Realm Configuration
 */
    public static void setRealmConfiguration(RealmConfiguration realmConfiguration){
        RealmController.realmConfiguration = realmConfiguration;
        realm.setDefaultConfiguration(realmConfiguration);
    }

   private static int activityCount = 0;

    /**
     * 添加数据,当数据有的时候就会更新
     *
     * @param realObject
     * @return
     */
    public static void add(final RealmObject realObject) {
        Realm realm = RealmController.getSaveRealm();

        realm.executeTransactionAsync(new Realm.Transaction() {
            public void execute(Realm realm) {
                if (realObject != null) {
                    realm.insertOrUpdate(realObject);
                }
            }
        });
    }

    /**
     * 添加数据List,当数据有的时候就会更新
     */
    public static void addAll(final List<? extends RealmObject> realObjects) {
        if (!CollectionUtils.isEmpty(realObjects)) {
            Realm realm = RealmController.getSaveRealm();
            realm.executeTransaction(new Realm.Transaction() {
                public void execute(Realm realm) {
                    realm.insertOrUpdate(realObjects);
                }
            });

        }
    }

    /**
     * 得到对应的本地数据的数量
     *
     * @param className
     * @return
     */
    public static long RealmDataCount(Class className) {
        Realm realm = RealmController.getSaveRealm();
        long count = realm.where(className).count();
        return count;
    }

    /**
     * 删除某个表
     */
    public static void deleteDB(final Class className) {
        Realm realm = RealmController.getSaveRealm();
        realm.executeTransactionAsync(
                new Realm.Transaction() {
                    public void execute(Realm realm) {
                        realm.where(className).findAll().clear();
                    }
                }
        );
    }

    /**
     * 据id来删除指定db下的某条数据
     * @param className
     */
    public static void deleteById(final Class className,final long id) {
        Realm realm = RealmController.getSaveRealm();
        realm.executeTransactionAsync(
                new Realm.Transaction() {
                    public void execute(Realm realm) {
                        realm.where(Book.class).equalTo("id",id).findFirst().deleteFromRealm();
                    }
                }
        );
    }

    /**
     * 获取到指定db下的所有数据
     *
     * @return
     */
    public static List<? extends RealmObject> findAll(Class className) {
        Realm realm = RealmController.getRealm();
        RealmResults objects = realm.where(className).findAllAsync();
        return objects;
    }


    /**
     * 根据id获得该条数据
     */
    public static RealmObject findById(Class className,long id) {
        Realm realm = RealmController.getRealm();
        RealmObject object;
        object = (RealmObject) realm.where(className).equalTo("id", id).findFirst();
        return object;
    }

    /**
     * 用于异步线程的realm 关闭
     *
     * @param realm
     */
    public static void closeReadRealm(Realm realm) {
        if (realm != null && !realm.isClosed() ) {
            realm.close();
        }
    }
}

注释应该都写得很清楚,而且我们还为Realm数据库预先设置了5个数据:

RealmInitialData.java

ublic class RealmInitialData implements Realm.Transaction {
     @Override
    public void execute(Realm realm) {
        Book book = new Book();
        book.setId((int) (1 + System.currentTimeMillis()));
        book.setAuthor("Reto Meier");
        book.setTitle("Android 4 Application Development");
        book.setImageUrl("https://api.androidhive.info/images/realm/1.png");
        book.setPages("666页");
        realm.insertOrUpdate(book);

        book = new Book();
        book.setId((int) (2 + System.currentTimeMillis()));
        book.setAuthor("Itzik Ben-Gan");
        book.setTitle("Microsoft SQL Server 2012 T-SQL Fundamentals");
        book.setImageUrl("https://api.androidhive.info/images/realm/2.png");
        book.setPages("111页");
        realm.insertOrUpdate(book);

        book = new Book();
        book.setId((int) (3 + System.currentTimeMillis()));
        book.setAuthor("Magnus Lie Hetland");
        book.setTitle("Beginning Python: From Novice To Professional Paperback");
        book.setImageUrl("https://api.androidhive.info/images/realm/3.png");
        book.setPages("222页");
        realm.insertOrUpdate(book);

        book = new Book();
        book.setId((int) (4 + System.currentTimeMillis()));
        book.setAuthor("Chad Fowler");
        book.setTitle("The Passionate Programmer: Creating a Remarkable Career in Software Development");
        book.setImageUrl("https://api.androidhive.info/images/realm/4.png");
        book.setPages("333页");
        realm.insertOrUpdate(book);

        book = new Book();
        book.setId((int) (5 + System.currentTimeMillis()));
        book.setAuthor("Yashavant Kanetkar");
        book.setTitle("Written Test Questions In C Programming");
        book.setImageUrl("https://api.androidhive.info/images/realm/5.png");
        book.setPages("444页");
        realm.insertOrUpdate(book);
    }
    public int hashCode(){
        return RealmInitialData.class.hashCode();
    }

    public boolean equals(Object obj){
        return obj!=null&&obj instanceof RealmInitialData;
    }
}

我们使用这个语句来为Realm初始化数据:

new RealmConfiguration.Builder(appContext).initialData(new RealmInitialData())

运用Realm

我们在代码中只需要在需要的地方调用Realm管理类的方法就可以了。

首先在OnCreate()方法中定义Realm:

 @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        RealmController.initializeRealmConfig(getActivity().getApplicationContext());
        setHasOptionsMenu(true);
        setRetainInstance(true);
        realm = RealmController.getRealm();
        if(savedInstanceState == null) {
            Toast.makeText(getContext(), "Press card item for edit, long press to remove item", Toast.LENGTH_LONG).show();
        }
        Log.i("oncreate","onCreate");
    }

在添加数据的时候调用方法:

public void onActivityResult(int requestCode, int resultCode, Intent data)
    {
        super.onActivityResult(requestCode, resultCode, data);
        // check if the request code is same as what is passed  here it is 2
        if(requestCode==2)
        {
            List<FileMsgModel> txtFiles = (List<FileMsgModel>) data.getSerializableExtra("MESSAGE");
            List<Book> books = new ArrayList<>();

            for(int i = 0;i<txtFiles.size();i++){
                Book book = new Book();
                FileMsgModel fsm = txtFiles.get(i);
                book.setTitle(fsm.getFileName());
                book.setPages(String.valueOf(Integer.parseInt(fsm.getFileSize())/4*4096/1000));
                book.setAuthor("佚名");
                book.setImageUrl("https://img1.doubanio.com/lpic/s1790028.jpg");
                books.add(book);
            }
            RealmController.addAll(books);
            setupRecycler();
        }
    }

设置适配器Adapter的时候从数据库中获得存储的数据:

private void setupRecycler() {
        RealmResults<Book> notes = realm.where(Book.class).findAll();
        adapter = new BooksAdapter(getContext(), notes);
        recycler.setAdapter(adapter);
    }

适配器

我们对数据进行的操作是点击编辑数据,长按删除数据:

创建一个适配器 ,该适配器将作为我们的数据集和我们的Activity之间的桥梁。在MainActivity中创建一个 名为BooksAdapter的新内部类 ,继承了RealmBasedRecyclerViewAdapter。
普通的RecyclerView只需要继承RealmRecyclerViewAdapter,这个开源库需要继承RealmBasedRecyclerViewAdapter。

public class BooksAdapter extends RealmBasedRecyclerViewAdapter<Book,BooksAdapter.CardViewHolder> {

 public BooksAdapter(Context context, RealmResults<Book> data) {
        super(context, data,true,false);
        this.mContext = context;
    }

  @Override
    public CardViewHolder onCreateRealmViewHolder(ViewGroup viewGroup, int i) {
        View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.want_read_item_layout,viewGroup,false);
        return new CardViewHolder(view);
    } 

@Override
    public void onBindRealmViewHolder(CardViewHolder cardViewHolder, int i) {
        final Book book = realmResults.get(i);
        if(book==null){
            return;
        }else{
            cardViewHolder.bind(book);
        }
    }

     /**
      *  并且也需要继承RealmViewHolder 
      */
   public class CardViewHolder extends RealmViewHolder{
        private final Context context;
        public CardView card;
        public TextView textTitle;
        public TextView textAuthor;
        public TextView textPages;
        public ImageView imageBackground;

        public CardViewHolder(View itemView) {
            super(itemView);
            this.context = itemView.getContext();
            card = (CardView) itemView.findViewById(R.id.card_books);
            textTitle = (TextView) itemView.findViewById(R.id.text_books_title);
            textAuthor = (TextView) itemView.findViewById(R.id.text_books_author);
            textPages = (TextView) itemView.findViewById(R.id.text_books_pages);
            imageBackground = (ImageView) itemView.findViewById(R.id.image_background);
        }

        public void bind(final Book book){
            final long id = book.getId();
            textTitle.setText(book.getTitle());
            textAuthor.setText(book.getAuthor());
            textPages.setText(book.getPages());
            if(book.getImageUrl()!=null){
                Glide.with(mContext)
                        .load(book.getImageUrl().replace("https","http"))
                        .asBitmap()
                        .fitCenter()
                        .into(imageBackground);
            }

            card.setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View view) {
                    RealmController.deleteById(Book.class,id);
                    notifyDataSetChanged();
                    Toast.makeText(mContext, book.getTitle() + " is removed from Realm", Toast.LENGTH_SHORT).show();
                    return false;
                }
            });

            card.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                    View content = inflater.inflate(R.layout.edit_item,null);
                    final EditText editTitle = (EditText) content.findViewById(R.id.title);
                    final EditText editAuthor = (EditText) content.findViewById(R.id.author);
                    final EditText editImagethum = (EditText) content.findViewById(R.id.thumbnail);
                    final EditText editPages = (EditText) content.findViewById(R.id.pages);

                    editTitle.setText(book.getTitle());
                    editAuthor.setText(book.getAuthor());
                    editImagethum.setText(book.getImageUrl());
                    editPages.setText(book.getPages());
                    AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
                    builder.setView(content)
                            .setTitle("Edit Book")
                            .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialogInterface, int i) {
                                    Book sari = (Book) RealmController.findById(Book.class,id);
                                    RealmController.getRealm().beginTransaction();
                                    if (sari == null) {
                                        Book book = RealmController.getRealm().createObject(Book.class);
                                    } else {
                                        sari.setTitle(editTitle.getText().toString());
                                        sari.setAuthor(editAuthor.getText().toString());
                                        sari.setPages(editPages.getText().toString());
                                        sari.setImageUrl(editImagethum.getText().toString());
                                    }
                                    RealmController.getRealm().commitTransaction();
                                    notifyDataSetChanged();

                                }
                            })
                            .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialogInterface, int i) {
                                    dialogInterface.dismiss();
                                }
                            });

                    AlertDialog dialog = builder.create();
                    dialog.show();
                }
            });
        }
    }
}

实际上跟继承普通的RecyclerViewAdapter没什么不同。

最后别忘了关闭Realm数据库

@Override
    public void onDestroy() {
        super.onDestroy();
        RealmController.closeReadRealm(realm); 
        }
    }

如果需要滑动删除,别忘了当我们创建我们的布局并设置app:rrvSwipeToDelete为true 。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值