Android Studio-基于SQLLITE实现登录注册功能

继启动界面之后,现在开始做登录界面和注册界面。需要看启动界面教学的,请戳我的博客Android Studio之启动界面教学 https://www.jianshu.com/p/7e0955291b18?tdsourcetag=s_pctim_aiomsg

其实安卓的登录注册,和JAVA是一样的,甚至于是极简版的JAVA登录注册,安卓太智能了,数据保存在sqllite中,完全不需要导包,而且还伴有可视化界面,简直无敌,安卓可以说是目前我们学过的最简单的语言,只是大家没有好好学罢了。如果大家认真学习,会发现真的超简单....

闲话不多说,接下来直接开始。

首先,先创建登录和注册两个activity,我这里取名为LoginActivity和RegisterActivity,我们取名要尽量做到规范,要让别人一眼就能看出来你这个是什么,不要总是取什么“aa”,"bb","cc"这种名字,让别人给你改代码看的都烦,估计你自己过一段时间都不知道你这文件是什么了,对吧?

image.png

创建两个activity,创建好了之后是这样的:

image.png

然后,我们再创建两个java.class文件,注意,不是创建activity。命名为User和DBOpenHelper,User就相当于我们java中的用户类,DBOpenHelper就相当于java中的DBUtils工具类,非常简单是不是?

image.png

接下来,我们先打开activity_login.xml,开始制作登录界面。 登录界面,我整体是相对布局, 在整体上方放三个东西,这三个东西也是相对布局合在一起称为一个top,下面是具体代码。

<?xml version="1.0" encoding="utf-8"?>
<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"
    android:background="#eeeeee"
    tools:context=".LoginActivity">
  
        <RelativeLayout
            android:id="@+id/rl_loginactivity_top"
            android:layout_width="match_parent"
            android:layout_height="70dp"
            android:background="@color/color_minefragment_top" >

            <ImageView
                android:id="@+id/iv_loginactivity_back"
                android:layout_width="30dp"
                android:layout_height="30dp"
                android:layout_alignParentTop="true"
                android:layout_marginLeft="10dp"
                android:layout_marginTop="20dp"
                android:background="@drawable/ic_left_back"
                android:clickable="true"
                android:onClick="onClick" />

            <TextView
                android:id="@+id/tv_loginactivity_login"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="登录"
                android:textColor="#fff"
                android:textSize="20dp"
                android:layout_toRightOf="@+id/iv_loginactivity_back"
                android:layout_centerVertical="true"
                android:layout_marginLeft="20dp"
                />
            <TextView
                android:id="@+id/tv_loginactivity_register"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="注册"
                android:textColor="#fff"
                android:textSize="20dp"
                android:layout_centerVertical="true"
                android:layout_alignParentRight="true"
                android:layout_marginRight="30dp"
                android:clickable="true"
                android:onClick="onClick"
                />
        </RelativeLayout>

顶部三个东西摆放好之后就该来摆放登录时候的两个文本输入框了用户名密码 这个明显的是LinerLayout,LinerLayout必须指明orientation 方向 要么垂直vertical 要么水平 horizontal,这里显然是垂直vertical.


        <LinearLayout
            android:id="@+id/ll_loginactivity_two"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:layout_below="@+id/rl_loginactivity_top"
            android:layout_marginTop="10dp"
            android:layout_marginLeft="5dp"
            android:layout_marginRight="5dp"
            >
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal">
                <TextView
                    android:id="@+id/tv_loginactivity_username"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="用户名:"/>
                <EditText
                    android:id="@+id/et_loginactivity_username"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:hint="手机号/邮箱/用户名"/>
            </LinearLayout>
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal">
                <TextView
                    android:id="@+id/tv_loginactivity_password"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="密    码:"/>
                <EditText
                    android:id="@+id/et_loginactivity_password"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:hint="登录密码"
                    android:inputType="textPassword"/>
            </LinearLayout>
        </LinearLayout>

填好用户名、密码后,就该点击登录按钮了
注意最后有一句: android:onClick="onClick"
这是应用了一个开源库,详细信息在loginActivity.java 中有注释

        <Button
            android:id="@+id/bt_loginactivity_login"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/ll_loginactivity_two"
            android:layout_marginTop="10dp"
            android:layout_marginLeft="5dp"
            android:layout_marginRight="5dp"
            android:background="@drawable/selector_loginactivity_button"
            android:text="登录"
            android:textColor="#fff"
            android:gravity="center"
            android:onClick="onClick"
            />
      
</RelativeLayout>

效果如下:

image.png

登录弄好了,注册界面就简单了,因为大体布局和控件是一样的,这里直接上代码

<?xml version="1.0" encoding="utf-8"?>
<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"
    android:background="#eeeeee"
    tools:context=".RegisterActivity">

    <RelativeLayout
        android:id="@+id/rl_registeractivity_top"
        android:layout_width="match_parent"
        android:layout_height="70dp"
        android:background="@color/color_minefragment_top"
        >
        <ImageView
            android:id="@+id/iv_registeractivity_back"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:background="@drawable/ic_left_back"
            android:layout_centerVertical="true"
            android:layout_marginLeft="10dp"
            android:clickable="true"
            android:onClick="onClick"
            />

        <TextView
            android:id="@+id/tv_registeractivity_register"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="注册"
            android:textColor="#fff"
            android:textSize="20dp"
            android:layout_toRightOf="@+id/iv_registeractivity_back"
            android:layout_centerVertical="true"
            android:layout_marginLeft="20dp"
            />
    </RelativeLayout>

    <LinearLayout
        android:id="@+id/ll_registeractivity_body"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:layout_below="@+id/rl_registeractivity_top"
        android:layout_marginTop="10dp"
        android:layout_marginLeft="5dp"
        android:layout_marginRight="5dp"
        >
        <!-- 第一个文本编辑框  输入用户名 -->
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">
            <TextView
                android:id="@+id/tv_registeractivity_username"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="用户名:"/>
            <EditText
                android:id="@+id/et_registeractivity_username"
                android:layout_width="match_parent"
                android:layout_height="50dp"
                android:hint="请输入用户名"
                android:gravity="center_vertical"
                android:layout_marginLeft="10dp"
                />
        </LinearLayout>
        <!-- 第二个文本编辑框  输入密码 -->
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">
            <TextView
                android:id="@+id/tv_registeractivity_password1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="密    码:"/>
            <EditText
                android:id="@+id/et_registeractivity_password1"
                android:layout_width="match_parent"
                android:layout_height="50dp"
                android:gravity="center_vertical"
                android:layout_marginLeft="10dp"
                android:inputType="textPassword"
                android:hint="请输入密码" />
        </LinearLayout>
        <!-- 第三个文本编辑框  输入年龄 -->
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">
            <TextView
                android:id="@+id/tv_registeractivity_password2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="年    龄:"/>
            <EditText
                android:id="@+id/et_registeractivity_password2"
                android:layout_width="match_parent"
                android:layout_height="50dp"
                android:hint="请输入年龄"
                android:gravity="center_vertical"
                android:layout_marginLeft="10dp"
                android:inputType="textPassword"
                />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginRight="15dp"
            android:layout_marginTop="10dp"
            android:orientation="horizontal" />
        <!-- 注册按钮 -->
        <Button
            android:id="@+id/bt_registeractivity_register"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:layout_marginLeft="5dp"
            android:background="@drawable/selector_loginactivity_button"
            android:textColor="#fff"
            android:text="注册"
            android:onClick="onClick"
            android:layout_marginTop="40dp"
            />

    </LinearLayout>
</RelativeLayout>

效果如下:(注,年龄是作业要求,必须要有的,所以我们加上这个控件,但是我偷了个懒,数据库中没有加上这个字段,因为年龄不影响登录啊,对吧?当然肯定有人没听懂,没听懂的就算了,不说了...)

image.png

登录和注册界面搭建好了,没有追求的同学,现在就可以点击右上角的红叉关闭这个网页了,因为你把界面都搭建起来,已经够你及格了,有兴趣继续往下看的同学,跟着我一起完成sqllite配置。

首先,把用户类写好,打开User,这个时候就是java功底,没什么好说的,直接上代码

package com.wxy.homework;

public class User {
    private String name;            //用户名
    private String password;        //密码

    public User(String name, String password) {
        this.name = name;
        this.password = password;

    }

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", password='" + password + '\'' +

                '}';
    }
}

打开DBHelper文件,声明一个AndroidSDK自带的数据库变量db,
写一个这个类的构造函数,参数为上下文context,所谓上下文就是这个类所在包的路径
指明上下文,数据库名,工厂默认空值,版本号默认从1开始
super(context,"db_test",null,1);
把数据库设置成可写入状态,除非内存已满,那时候会自动设置为只读模式
不过,以现如今的内存容量,估计一辈子也见不到几次内存占满的状态
db = getReadableDatabase();

package com.wxy.homework;

import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

import java.util.ArrayList;

public class DBOpenHelper extends SQLiteOpenHelper {

    private SQLiteDatabase db;
    public DBOpenHelper(Context context){
        super(context,"db_test",null,1);
        db = getReadableDatabase();
    }

重写两个必须要重写的方法,因为class DBOpenHelper extends SQLiteOpenHelper
而这两个方法是 abstract 类 SQLiteOpenHelper 中声明的 abstract 方法
所以必须在子类 DBOpenHelper 中重写 abstract 方法
想想也是,为啥规定这么死必须重写?
因为,一个数据库表,首先是要被创建的,然后免不了是要进行增删改操作的
所以就有onCreate()、onUpgrade()两个方法

    @Override
    public void onCreate(SQLiteDatabase db){
        db.execSQL("CREATE TABLE IF NOT EXISTS user(" +
                "_id INTEGER PRIMARY KEY AUTOINCREMENT," +
                "name TEXT," +
                "password TEXT)");
    }
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){
        db.execSQL("DROP TABLE IF EXISTS user");
        onCreate(db);
    }

接下来写自定义的增删改查方法
这些方法,写在这里归写在这里,以后不一定都用
* add()
* delete()
* update()
* getAllData()

    public void add(String name,String password){
        db.execSQL("INSERT INTO user (name,password) VALUES(?,?)",new Object[]{name,password});
    }
    public void delete(String name,String password){
        db.execSQL("DELETE FROM user WHERE name = AND password ="+name+password);
    }
    public void updata(String password){
        db.execSQL("UPDATE user SET password = ?",new Object[]{password});
    }

前三个没啥说的,都是一套的看懂一个其他的都能懂了
下面重点说一下查询表user全部内容的方法
我们查询出来的内容,需要有个容器存放,以供使用,
所以定义了一个ArrayList类的list
有了容器,接下来就该从表中查询数据了,
这里使用游标Cursor,这就是数据库的功底了,
在Android中我就不细说了,因为我数据库功底也不是很厚,
但我知道,如果需要用Cursor的话,第一个参数:"表名",中间5个:null,
最后是查询出来内容的排序方式:"name DESC"
游标定义好了,接下来写一个while循环,让游标从表头游到表尾
在游的过程中把游出来的数据存放到list容器中

    public ArrayList<User> getAllData(){

        ArrayList<User> list = new ArrayList<User>();
        Cursor cursor = db.query("user",null,null,null,null,null,"name DESC");
        while(cursor.moveToNext()){
            String name = cursor.getString(cursor.getColumnIndex("name"));
            String password = cursor.getString(cursor.getColumnIndex("password"));
            list.add(new User(name,password));
        }
        return list;
    }
}

然后,我们打开LoginActivity,我直接把不需要的东西全部去掉了,只需要将高亮代码拷贝即可。

package com.wxy.homework;

import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import java.util.ArrayList;
public class LoginActivity extends AppCompatActivity implements View.OnClickListener {

声明自己写的 DBOpenHelper 对象
DBOpenHelper(extends SQLiteOpenHelper) 主要用来
创建数据表
然后再进行数据表的增、删、改、查操作

    private DBOpenHelper mDBOpenHelper;
    private TextView mTvLoginactivityRegister;
    private RelativeLayout mRlLoginactivityTop;
    private EditText mEtLoginactivityUsername;
    private EditText mEtLoginactivityPassword;
    private LinearLayout mLlLoginactivityTwo;
    private Button mBtLoginactivityLogin;

创建 Activity 时先来重写 onCreate() 方法
保存实例状态
super.onCreate(savedInstanceState);
设置视图内容的配置文件
setContentView(R.layout.activity_login);
上面这行代码真正实现了把视图层 View 也就是 layout 的内容放到 Activity 中进行显示
初始化视图中的控件对象 initView()
实例化 DBOpenHelper,待会进行登录验证的时候要用来进行数据查询
mDBOpenHelper = new DBOpenHelper(this);

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);

        initView();

        mDBOpenHelper = new DBOpenHelper(this);
    }

onCreae()中大的布局已经摆放好了,接下来就该把layout里的东西
声明、实例化对象然后有行为的赋予其行为
这样就可以把视图层View也就是layout 与 控制层 Java 结合起来了

    private void initView() {
        // 初始化控件
        mBtLoginactivityLogin = findViewById(R.id.bt_loginactivity_login);
        mTvLoginactivityRegister = findViewById(R.id.tv_loginactivity_register);
        mRlLoginactivityTop = findViewById(R.id.rl_loginactivity_top);
        mEtLoginactivityUsername = findViewById(R.id.et_loginactivity_username);
        mEtLoginactivityPassword = findViewById(R.id.et_loginactivity_password);
        mLlLoginactivityTwo = findViewById(R.id.ll_loginactivity_two);

        // 设置点击事件监听器
        mBtLoginactivityLogin.setOnClickListener(this);
        mTvLoginactivityRegister.setOnClickListener(this);
    }

    public void onClick(View view) {
        switch (view.getId()) {
            // 跳转到注册界面
            case R.id.tv_loginactivity_register:
                startActivity(new Intent(this, RegisterActivity.class));
                finish();
                break;

登录验证:
从EditText的对象上获取文本编辑框输入的数据,并把左右两边的空格去掉
String name = mEtLoginactivityUsername.getText().toString().trim();
String password = mEtLoginactivityPassword.getText().toString().trim();
进行匹配验证,先判断一下用户名密码是否为空,
if (!TextUtils.isEmpty(name) && !TextUtils.isEmpty(password))
再进而for循环判断是否与数据库中的数据相匹配
if (name.equals(user.getName()) && password.equals(user.getPassword()))
一旦匹配,立即将match = true;break;
否则 一直匹配到结束 match = false;
登录成功之后,进行页面跳转:
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
finish();//销毁此Activity

            case R.id.bt_loginactivity_login:
                String name = mEtLoginactivityUsername.getText().toString().trim();
                String password = mEtLoginactivityPassword.getText().toString().trim();
                if (!TextUtils.isEmpty(name) && !TextUtils.isEmpty(password)) {
                    ArrayList<User> data = mDBOpenHelper.getAllData();
                    boolean match = false;
                    for (int i = 0; i < data.size(); i++) {
                        User user = data.get(i);
                        if (name.equals(user.getName()) && password.equals(user.getPassword())) {
                            match = true;
                            break;
                        } else {
                            match = false;
                        }
                    }
                    if (match) {
                        Toast.makeText(this, "登录成功", Toast.LENGTH_SHORT).show();
                        Intent intent = new Intent(this, MainActivity.class);
                        startActivity(intent);
                        finish();//销毁此Activity
                    } else {
                        Toast.makeText(this, "用户名或密码不正确,请重新输入", Toast.LENGTH_SHORT).show();
                    }
                } else {
                    Toast.makeText(this, "请输入你的用户名或密码", Toast.LENGTH_SHORT).show();
                }
                break;
        }
    }
}

紧接着,打开RegisterActivity,完成注册功能,

package com.wxy.homework;


import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;

此类 implements View.OnClickListener 之后,
就可以把onClick事件写到onCreate()方法之外
这样,onCreate()方法中的代码就不会显得很冗余

public class RegisterActivity extends AppCompatActivity implements View.OnClickListener {

    private String realCode;
    private DBOpenHelper mDBOpenHelper;
    private Button mBtRegisteractivityRegister;
    private RelativeLayout mRlRegisteractivityTop;
    private ImageView mIvRegisteractivityBack;
    private LinearLayout mLlRegisteractivityBody;
    private EditText mEtRegisteractivityUsername;
    private EditText mEtRegisteractivityPassword1;
    private EditText mEtRegisteractivityPassword2;
    private EditText mEtRegisteractivityPhonecodes;
    private ImageView mIvRegisteractivityShowcode;
    private RelativeLayout mRlRegisteractivityBottom;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_register);

        initView();

        mDBOpenHelper = new DBOpenHelper(this);


    }

    private void initView(){
        mBtRegisteractivityRegister = findViewById(R.id.bt_registeractivity_register);
        mRlRegisteractivityTop = findViewById(R.id.rl_registeractivity_top);
        mIvRegisteractivityBack = findViewById(R.id.iv_registeractivity_back);
        mLlRegisteractivityBody = findViewById(R.id.ll_registeractivity_body);
        mEtRegisteractivityUsername = findViewById(R.id.et_registeractivity_username);
        mEtRegisteractivityPassword1 = findViewById(R.id.et_registeractivity_password1);
        mEtRegisteractivityPassword2 = findViewById(R.id.et_registeractivity_password2);



        mIvRegisteractivityBack.setOnClickListener(this);

        mBtRegisteractivityRegister.setOnClickListener(this);
    }

    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.iv_registeractivity_back: //返回登录页面
                Intent intent1 = new Intent(this, LoginActivity.class);
                startActivity(intent1);
                finish();
                break;

            case R.id.bt_registeractivity_register:    //注册按钮
                //获取用户输入的用户名、密码、验证码
                String username = mEtRegisteractivityUsername.getText().toString().trim();
                String password = mEtRegisteractivityPassword1.getText().toString().trim();

                //注册验证
                if (!TextUtils.isEmpty(username) && !TextUtils.isEmpty(password)  ) {

                        //将用户名和密码加入到数据库中
                        mDBOpenHelper.add(username, password);
                        Intent intent2 = new Intent(this, MainActivity.class);
                        startActivity(intent2);
                        finish();
                        Toast.makeText(this,  "验证通过,注册成功", Toast.LENGTH_SHORT).show();
                }else {
                    Toast.makeText(this, "未完善信息,注册失败", Toast.LENGTH_SHORT).show();
                }
                break;
        }
    }
}

至此,登录注册功能已全部实现,激动人心的时候到了,点击build跑一遍程序看看效果怎么样

可以看到,首先是来到登录界面,如果直接点登录,下方会有弹窗提示“请输入用户名和密码

image.png

我们再来测试一下注册,点击右上角的注册,可以看到这里完美跳转到注册界面。

image.png

我们输入用户信息,然后点击注册,看看效果怎么样。

image.png

可以看到,注册成功,并且跳转到主界面,下方会有弹窗提示“验证通过,注册成功

image.png

此时,我们点击rebuild重新启动,测试刚刚注册的信息,能否在登录界面直接用

image.png

我们点击登录,发现完美运行,下方提示“登录成功”

image.png

好啦,各位同学,我想我写的够详细了,希望能够帮到大家。

咱们就差一个备忘录了,
未完待续....

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容