数据库的使用(Firebase 跟 Redis)总结

数据库的使用(Firebase 跟 Redis)总结

一、FireBase Database 的使用 【Android】

最近使用了FireBase 的Database,感觉入坑了,虽然国内需要科学“那个”,不过还是很舒服,抛弃了服务器的开发,直接写前端,舒服。

这个具体配置还有api key的获取这里不多说,我们来看看项目中具体如何使用。
可能会误人子弟,给别人做demo比较急,有些地方多见谅。

1.实现注册功能

Java

    //firebase database
    private FirebaseDatabase mDatabase;
    private DatabaseReference myRef;
    //init database
    mDatabase = FirebaseDatabase.getInstance();
    //search from users
    myRef = mDatabase.getReference("users");

这个地方是初始化,并获得users的怎么说,users是个啥,哈哈差点要说“表”。看一下firebase的后台吧,这个相当于users key 对应的 value,也就是说mDatabase.getReference(“users”);之后我们拿到了users的调用权。
这个user一看就很简陋,哈哈,demo,demo。
数据库的使用(Firebase 跟 Redis)总结
把注册信息传到firebase

myRef.child(et_username.getText().toString())
                                .setValue(et_password.getText().toString())
                                .addOnSuccessListener(new OnSuccessListener<Void>() {
                                    @Override
                                    public void onSuccess(Void aVoid) {
                                        progressDialog.dismiss();
                                        Toast.makeText(RegisterActivity.this, "Register Success!!!", Toast.LENGTH_LONG).show();
                                    }
                                })
                                .addOnFailureListener(new OnFailureListener() {
                                    @Override
                                    public void onFailure(@NonNull Exception e) {
                                        progressDialog.dismiss();
                                        Toast.makeText(RegisterActivity.this, "Register Fail!!!", Toast.LENGTH_LONG).show();
                                    }
                                });

这个地方myRef.child(“username”).setValue(“password”),可以看出,我们把key-value的用户名密码存储到users中去了。
后边这个.addOnSuccessListener(new OnSuccessListener()是监听事件,插入成功的一个回掉。

完整代码

package com.example.cacp;

import android.app.ProgressDialog;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;

public class RegisterActivity extends AppCompatActivity {

    //Ui
    private EditText et_username;
    private EditText et_password;
    private EditText et_password2;
    private Button btn_register;
    //firebase database
    private FirebaseDatabase mDatabase;
    private DatabaseReference myRef;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_register);
        //bind view
        et_username = findViewById(R.id.input_username);
        et_password = findViewById(R.id.input_password);
        et_password2 = findViewById(R.id.input_password_repeat);
        btn_register = findViewById(R.id.btn_register);
        //init database
        mDatabase = FirebaseDatabase.getInstance();
        //search from users
        myRef = mDatabase.getReference("users");
        //button listener
        btn_register.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //progress
                final ProgressDialog progressDialog = new ProgressDialog(RegisterActivity.this,
                R.style.AppTheme_Dark_Dialog);
                progressDialog.setIndeterminate(true);
                progressDialog.setMessage("Connecting...");
                progressDialog.show();
                if (et_username.getText().toString().isEmpty() || et_password.getText().toString().isEmpty() || et_password2.getText().toString().isEmpty()) {
                    Toast.makeText(RegisterActivity.this, "Please enter user information!!!", Toast.LENGTH_LONG).show();
                    progressDialog.dismiss();
                } else {
                    if (et_password.getText().toString().equals(et_password2.getText().toString())) {
                        //insert user information
                        myRef.child(et_username.getText().toString())
                                .setValue(et_password.getText().toString())
                                .addOnSuccessListener(new OnSuccessListener<Void>() {
                                    @Override
                                    public void onSuccess(Void aVoid) {
                                        progressDialog.dismiss();
                                        Toast.makeText(RegisterActivity.this, "Register Success!!!", Toast.LENGTH_LONG).show();
                                    }
                                })
                                .addOnFailureListener(new OnFailureListener() {
                                    @Override
                                    public void onFailure(@NonNull Exception e) {
                                        progressDialog.dismiss();
                                        Toast.makeText(RegisterActivity.this, "Register Fail!!!", Toast.LENGTH_LONG).show();
                                    }
                                });
                    } else {
                        progressDialog.dismiss();
                        Toast.makeText(RegisterActivity.this, "The two passwords do not match!!!", Toast.LENGTH_LONG).show();
                    }
                }
            }
        });
    }
}

2.实现登陆功能

这个就更误人子弟了,会把整个users中的数据都会拉到本地,哈哈,密码也被人看到了,demo,demo。
初始化的都一样,也是拿到users的调用权

myRef.addValueEventListener(new ValueEventListener() {
                        @Override
                        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                            progressDialog.dismiss();
                            //auth username password
                            if(dataSnapshot.child(et_username.getText().toString()).exists()){
                                String password = dataSnapshot.child(et_username.getText().toString()).getValue().toString();
                                if(password.equals(et_password.getText().toString())){
                                    Singleton.getInstance().setUsername(et_username.getText().toString());
                                    Toast.makeText(LoginActivity.this,"Login Success!!!",Toast.LENGTH_LONG).show();
                                    startActivity(new Intent(LoginActivity.this,Main2Activity.class));
                                    finish();
                                }else{
                                    Toast.makeText(LoginActivity.this,"Password Mistake!!!",Toast.LENGTH_LONG).show();
                                }
                            }else{
                                Toast.makeText(LoginActivity.this,"The username does not exist!!!",Toast.LENGTH_LONG).show();
                            }

                        }

                        @Override
                        public void onCancelled(@NonNull DatabaseError databaseError) {
                            progressDialog.dismiss();
                        }
                    });

这个 DataSnapshot dataSnapshot 参数中获取了users的全部数据……
使用 dataSnapshot.child(“username”).exist()判断一下这个用户名是不是存在。
如果存在, 再获取一下这个用户名对应的密码dataSnapshot.child(“username”).getValue().toString(),然后跟输入框里的比较一下,没问题就没问题了。……
完整代码

package com.example.cacp;

import android.Manifest;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.provider.Settings;
import android.support.annotation.NonNull;
import android.support.v7.app.AlertDialog;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;

public class LoginActivity extends XPermissionActivity {
    //ui
    private EditText et_username;
    private EditText et_password;
    private Button btn_login;
    private TextView tx_register;
    private Context mContext;
    private DatabaseReference myRef;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);
        mContext = this;
        //bind view
        et_username = findViewById(R.id.input_username);
        et_password = findViewById(R.id.input_password);
        btn_login = findViewById(R.id.btn_login);
        tx_register = findViewById(R.id.tv_register);
        // Write a message to the database
        FirebaseDatabase database = FirebaseDatabase.getInstance();
        myRef = database.getReference("users");
        tx_register.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                startActivity(new Intent(LoginActivity.this,RegisterActivity.class));
            }
        });
        btn_login.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                requireAll();
            }
        });
    }
    //Apply for the necessary permissions first
    private void requireAll() {
        requestPermission(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,
                Manifest.permission.ACCESS_FINE_LOCATION
        }, new XPermissionActivity.PermissionHandler() {
            @Override
            public void onGranted() {
                //progress
                final ProgressDialog progressDialog = new ProgressDialog(LoginActivity.this,
                        R.style.AppTheme_Dark_Dialog);
                progressDialog.setIndeterminate(true);
                progressDialog.setMessage("Connecting...");
                progressDialog.show();
                if(et_username.getText().toString().isEmpty()||et_password.getText().toString().isEmpty()){
                    Toast.makeText(LoginActivity.this,"Please input username or password",Toast.LENGTH_LONG).show();
                    progressDialog.dismiss();
                }else{
                    myRef.addValueEventListener(new ValueEventListener() {
                        @Override
                        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                            progressDialog.dismiss();
                            //auth username password
                            if(dataSnapshot.child(et_username.getText().toString()).exists()){
                                String password = dataSnapshot.child(et_username.getText().toString()).getValue().toString();
                                if(password.equals(et_password.getText().toString())){
                                    Singleton.getInstance().setUsername(et_username.getText().toString());
                                    Toast.makeText(LoginActivity.this,"Login Success!!!",Toast.LENGTH_LONG).show();
                                    startActivity(new Intent(LoginActivity.this,Main2Activity.class));
                                    finish();
                                }else{
                                    Toast.makeText(LoginActivity.this,"Password Mistake!!!",Toast.LENGTH_LONG).show();
                                }
                            }else{
                                Toast.makeText(LoginActivity.this,"The username does not exist!!!",Toast.LENGTH_LONG).show();
                            }

                        }

                        @Override
                        public void onCancelled(@NonNull DatabaseError databaseError) {
                            progressDialog.dismiss();
                        }
                    });
                }
            }

            @Override
            public boolean onNeverAsk() {
                new AlertDialog.Builder(mContext)
                        .setTitle("Permission to apply for")
                        .setMessage("Enable permissions in Settings - applications - permissions to ensure the normal use of functions")
                        .setPositiveButton("Allow", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                                Uri uri = Uri.fromParts("package", getPackageName(), null);
                                intent.setData(uri);
                                startActivity(intent);
                                dialog.dismiss();
                            }
                        })
                        .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialogInterface, int i) {
                                finish();
                            }
                        })
                        .setCancelable(false)
                        .show();
                return true;
            }
        });
    }
}


3.实现用户评分功能

我们登陆成功后,需要对上一篇文章搜索到附近的公园进行评分,这个跟注册差不多。
看一下firebase后台。
数据库的使用(Firebase 跟 Redis)总结
获取rating的操作权

        //firebase database
        FirebaseDatabase database = FirebaseDatabase.getInstance();
        final DatabaseReference myRef = database.getReference("rating");

插入评分,只是多了个child

myRef.child(id).child(Singleton.getInstance().getUsername())
                        .setValue(String.valueOf(v))
                        .addOnSuccessListener(new OnSuccessListener<Void>() {
                            @Override
                            public void onSuccess(Void aVoid) {
                                progressDialog.dismiss();
                                Toast.makeText(DetailActivity.this, "Rating Success!!!", Toast.LENGTH_LONG).show();
                            }
                        })
                        .addOnFailureListener(new OnFailureListener() {
                            @Override
                            public void onFailure(@NonNull Exception e) {
                                progressDialog.dismiss();
                                Toast.makeText(DetailActivity.this, "Rating Fail!!!", Toast.LENGTH_LONG).show();
                            }
                        });

貌似没有什么区别,我为什么要贴出来……
myRef.child(id).child(“username”).setValue(“3.5”)
公园的id,用户名,评分,没毛病。
记错了,不是这个项目里的,然后再加一点别的项目里的,哈哈,不是项目,demo,demo


4.实现文章评论功能

可以看一下firebase的后台,这里,comments相当于sql中的表吧,我们下一层是文章id,例如这里的class of 1927 bear,然后下一层,是一个随机key,然后下一层就是用户的评论了,怎么样,这个稍微复杂一点吧。
数据库的使用(Firebase 跟 Redis)总结
这个怎么实现呢,看代码。
初始化一样

    //firebase database
    private FirebaseDatabase mDatabase;
    private DatabaseReference myRef;
    mDatabase = FirebaseDatabase.getInstance();
    myRef = mDatabase.getReference("comments").child(title);

这里我们获取了comments的操作权,并且向下一层扩展了一下,我们点击进入这个文章后,获取了文章的id,就是这个title,也就是我们对这篇文章进行评论,我们的评论都会被插入到这个文章对应的表中。又“表”了,SQL陷的太深。。。。

存储用户评论信息

Comment comment = new Comment(editText.getText().toString(), getUsername(), new Date());
myRef.push().setValue(comment);

这里我们用了Comment,这个是我们自己建的Bean,把一条评论作为对象进行存储。
先说一下这个 push(),就是上边我们看到的文章下一层的随机key,setValue不用多说了。
然后我们看一下Comment类
Comment.java

package com.example.cs160_sp18.prog3;

import java.util.Date;

// custom class made for storing a message. you can update this class
public class Comment {

    public String text;
    public String username;
    public Date date;

    public Comment(){

    }
    public Comment(String text, String username, Date date) {
        this.text = text;
        this.username = username;
        this.date = date;
    }
    // returns a string indicating how long ago this post was made
    protected String elapsedTimeString() {
        long diff = new Date().getTime() - date.getTime();
        long seconds = diff / 1000;
        long minutes = seconds / 60;
        long hours = minutes / 60;
        long days = hours / 24;
        int daysInt = Math.round(days);
        int hoursInt = Math.round(hours);
        int minutesInt = Math.round(minutes);
        if (daysInt == 1) {
            return "1 day";
        } else if (daysInt > 1) {
            return Integer.toString(daysInt) + " days";
        } else if (hoursInt == 1) {
            return "1 hour";
        } else if (hoursInt > 1) {
            return Integer.toString(hoursInt) + " hours";
        } else {
            return "less than an hour";
        }
    }
}

有用户名,评论内容,评论时间,下边还有一个计算多久之前发的这条评论。可以看一下demo界面的展示。
数据库的使用(Firebase 跟 Redis)总结

还没完,我们发送了一条评论之后,可以立即就显示在上班,使用firebase监听数据的改变,并把数据添加到recylerview中。

myRef.addChildEventListener(new ChildEventListener() {
            @Override
            public void onChildAdded(DataSnapshot dataSnapshot, String s) {
                if (dataSnapshot != null && dataSnapshot.getValue() != null) {
                    try {
                        Comment comment = dataSnapshot.getValue(Comment.class);
                        Log.d("xbw12138",comment.text);
                        comments.add(comment);
                        commentAdapter.notifyDataSetChanged();
                        editText.setText("");
                    } catch (Exception ex) {
                        Log.e("MYERROR", ex.getMessage());
                    }
                }
            }
            @Override
            public void onChildChanged(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {

            }

            @Override
            public void onChildRemoved(@NonNull DataSnapshot dataSnapshot) {

            }

            @Override
            public void onChildMoved(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {

            }

            @Override
            public void onCancelled(DatabaseError databaseError) {
                Log.d("MYERROR", databaseError.getMessage());
            }
        });
        commentAdapter = new CommentAdapter(this, comments);
        recyclerView.setAdapter(commentAdapter);
    }

这里我们也使用了Comment来承接一条评论数据。
感觉一下说的有点多,那个Redis先不在这里说了,也不是一个内容,误人子弟了各位,完全是为了方便实现demo,记录一下。有需要demo的可以留言评论。