学校开了Android课,最后让交一个大作业。正好拿来练练手,记录下思路。也希望能给有需要的朋友们一些帮助。恩,纯小白教程,大神们可以绕路了。
作业的题目是这样的:
考试APP系统:
1)要求有用户登陆功能:从远程服务器进行登陆验证。
2)要有考试测试界面,主要是选择、判断、简答题目测试。
3)要有统计成绩界面和错题显示界面。
评分标准:
1、界面设计占评分的30%
2、系统运行正确; 功能完善;工作量充分; 系统实现有一定的技术的难度。50%
3、要求有适当的系统主要模块的文档说明和代码注释。
4、直接将数据库文件(数据库一定要备份成SQL语句格式,指明数据库)和项目文件提交。

乍一看挺简单的,真要研究起来,写的实用一些,还真有点不知如何下手,那跟着我的思路,一起来吧!恩,不想看思路的,可以直接戳Android源码下载源码来看了。

下载地址:

可以直接下载,github我也正在整理,有空了会放上去。

百度网盘放了一份(服务器代码和数据库都有),应该可以下载。如果失效了我再更新。
链接: https://pan.baidu.com/s/1uFhsBpkQdtTvUmBj4T4pbA 提取码: kexy

功能需求设计:

  • 登录注册
  • 答题:选择题,判断题,简答题
  • 答题得分计算
  • 错题查看

最后效果

android 选择题题目 android答题实现 简书_jsp

总体思路

总体思路是这样的,App通过http连接服务器,进行登录或者注册服务,登录成功之后,服务器查询数据库并以json的形式返回试题数据。App接收数据之后,解析并存到本地数据库,然后展示给用户答题。点击交卷按钮后,进行评分并可进行错题查看。内容比较杂乱,大家可以根据目录来快速查看自己需要或者感兴趣的地方。


文章目录

  • 下载地址:
  • 功能需求设计:
  • 最后效果
  • 总体思路
  • 数据库设计
  • jsp程序
  • 登录注册
  • 登录
  • 注册
  • json格式设计
  • 答题
  • json格式设计
  • Android程序设计
  • 应该有哪些界面?
  • 用到了哪些知识?依赖了什么第三方框架?
  • 页面详解
  • BaseActivity(Activity基类)
  • SplashActivity(启动页面)
  • LoginActivity(登录页面)
  • SignupActivity(注册页面)
  • AnswerActivity ,AnswerFragment(答题页面)


数据库设计

首先,就登录注册的功能来说,得先有一个用户表,包含用户名,密码,id号这些基本的内容。我在这里又加了一个权限字段,用来返回状态。(设置权限字段,方便日后进行扩展,可设置用不同数字代表不同等级或身份)

tbl_user_info

字段

类型

含义

id

int(自增长主键)

用户唯一标识符

username

varchar

用户

password

varchar

密码

perssion

varchar(默认为0)

权限

其次,就是题库了。为了使项目具有实用性,减小安装包体积,便于更新修正,题库同样也需要放在服务器上才合适。

tbl_question

字段

类型

含义

id

int(自增长主键)

题目唯一标识id

q_type:

int

题型: 1:选择 2:判断 3:简答

title:

varchar

问题

optionA:

varchar

选项A

optionB:

varchar

选项B

optionC:

varchar

选项C

optionD:

varchar

选项D

tips:

varchar

提示

answer:

varchar

答案

explain:

varchar

解释

write_answer:

varchar

你的答案

jsp程序

jsp依赖了两个jar包,分别是连接mysql的驱动:mysql-connector-java-5.1.34-bin还有生成json用的:json 。为了减少代码的耦合性,这里采用MVC模式进行设计。(自以为是MVC)。目录结构如下:

android 选择题题目 android答题实现 简书_android_02

登录注册

###连接数据库
数据库操作类,封装了连接,查询,关闭数据库的方法。大家如果使用这部分代码,别忘了把数据库连接常量改成自己的。

//****连接数据库**DBManager***
public class DBManager {

    // 数据库连接常量
    public static final String DRIVER = "com.mysql.jdbc.Driver";
    public static final String USER = "root";
    public static final String PASS = "root";
    public static final String URL = "jdbc:mysql://localhost:3306/shop";

    // 静态成员,支持单态模式
    private static DBManager per = null;
    private Connection conn = null;
    private Statement stmt = null;

    // 单态模式-懒汉模式
    private DBManager() {
    }

    public static DBManager createInstance() {
        if (per == null) {
            per = new DBManager();
            per.initDB();
        }
        return per;
    }

    // 加载驱动
    public void initDB() {
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 连接数据库,获取句柄+对象
    public void connectDB() {
        System.out.println("Connecting to database...");
        try {
            conn = DriverManager.getConnection(URL, USER, PASS);
            stmt = conn.createStatement();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        System.out.println("SqlManager:Connect to database successful.");
    }

    // 关闭数据库 关闭对象,释放句柄
    public void closeDB() {
        System.out.println("Close connection to database..");
        try {
            stmt.close();
            conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        System.out.println("Close connection successful");
    }

    // 查询
    public ResultSet executeQuery(String sql) {
        ResultSet rs = null;
        try {
            rs = stmt.executeQuery(sql);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return rs;
    }
   
    // 增添/删除/修改
    public int executeUpdate(String sql) {
        int ret = 0;
        try {
            ret = stmt.executeUpdate(sql);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return ret;
    }
}

登录

客户端提交过来一个用户名,一个密码,jsp连接数据库查询,如果两者都符合,返回登录成功信息,否则返回登录失败信息。(我这里用权限来代表,当权限>-1即为登录成功)。

注册

客户端同样提交过来一个用户名,一个密码,但是需要首先查询数据库,看看该用户名是否已被注册,若没有,则执行数据库插入操作。成功则返回注册成功,否则返回失败信息。

//****服务代码****
public class StartService {
	/**
	 * 登录方法
	 * @param username
	 * @param password
	 * @return 登录成功与否
	 */
	public HashMap<String, String> login(String username, String password) {

		HashMap<String, String> hashMap = new HashMap<String, String>();
		// 获取Sql查询语句
		String logSql = "select perssion from userinfo where username ='"
				+ username + "' and password ='" + password + "'";
		System.out.println(logSql);
		// 获取DB对象
		DBManager sql = DBManager.createInstance();
		sql.connectDB();

		hashMap.put("permission", "-1");
		hashMap.put("username", username);

		// 操作DB对象
		try {
			ResultSet rs = sql.executeQuery(logSql);
			if (rs.next()) {
				hashMap.put("permission", rs.getInt(1) + "");
				System.out.print("权限===" + rs.getInt(1) + "\t");
				sql.closeDB();
				return hashMap;
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		sql.closeDB();
		return hashMap;
	}

	/**
	 * 注册方法
	 * @param username
	 * @param password
	 * @return 注册成功与否
	 */
	public HashMap<String, String> register(String username, String password) {

		HashMap<String, String> hashMap = new HashMap<String, String>();
		hashMap.put("username", username);
		hashMap.put("msg", "notok");
		if (this.namerepeat(username)) {
			hashMap.put("msg", "rename");
		} else {
			// 获取Sql查询语句
			String regSql = "insert into userinfo(username,password) values('"
					+ username + "','" + password + "')";
			System.out.println(regSql);

			// 获取DB对象
			DBManager sql = DBManager.createInstance();
			sql.connectDB();

			int ret = sql.executeUpdate(regSql);
			if (ret != 0) {
				hashMap.put("msg", "ok");
				sql.closeDB();
				return hashMap;
			}
			sql.closeDB();
		}

		return hashMap;
	}

	/**
	 * 检测该账户是否已经注册
	 * 
	 * @param username
	 * @return 注册状态
	 */
	public Boolean namerepeat(String username) {
		String checkSql = "select username from userinfo where username ='"
				+ username + "'";
		// 获取Sql查询语句
		System.out.println(checkSql);

		// 获取DB对象
		DBManager sql = DBManager.createInstance();
		sql.connectDB();

		// 操作DB对象
		try {
			ResultSet rs = sql.executeQuery(checkSql);
			if (rs.next()) {

				sql.closeDB();
				return true;
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		sql.closeDB();
		return false;
	}
}

登录注册部分的代码基本一样,只把 serv.login变成serv.reglet就可以了。

//****登录代码****
String username = request.getParameter("username");
String password = request.getParameter("password");
username = new String(username.getBytes("ISO-8859-1"), "UTF-8");
System.out.println("客户端参数:" + username + "  ======  " + password);
	// 新建服务对象,默认权限为-1(未登录状态)
	StartService serv = new StartService();
	int permission = -1;
	HashMap<String, String> logiii = serv.login(username, password);
	String a = logiii.get("username");
	// 登陆验证处理(权限>-1为登录成功)
	if ("-1".equals(logiii.get("permission"))) {
		// 登录失败
		System.out.print("登录失败Failed");
	} else {
		// 登陆成功
		permission = Integer.parseInt(logiii.get("permission"));
	}
	JSONObject jsonObj = new JSONObject();
	try {
		jsonObj.put("username", username);
		jsonObj.put("permission", permission);
		System.out.println(jsonObj);
		// 返回信息到客户端
		response.setCharacterEncoding("UTF-8");
		response.setContentType("text/html");
		PrintWriter out = response.getWriter();
		out.print(jsonObj);
		out.flush();
		out.close();
	} catch (JSONException e) {
		e.printStackTrace();
	}

json格式设计

注册结果

{
    "username": "001",
    "msg": "ok"
}

登录结果

{
    "username": "001",
    "permission": 0
}

答题

json格式设计

{
    "status": ok,  //连接状态
    "code": "200"   //错误代码
    "messages": [   //题目内容
        {
            "_id": 1,   //题目id
            "title": "1+1=?"  //题目
            "q_type": 0,  //题目类型
            "optionA": "1",  //A选项
            "optionB": "2",  //B选项
            "optionC": "3",  //C选项
            "optionD": "4",  //D选项
            "tips”:"这么简单还要提示?",  //提示
            "answer": "B",  //答案
        },
        {
            "_id": 2,
             "title": "2+2=?" 
            "q_type": 0, 
            "optionA": "1", 
            "optionB": "2", 
            "optionC": "3", 
            "optionD": "4",
            "tips":"这么简单还要提示?",  
            "answer": "D",
        }
    ],
}

Android程序设计

恩,这才是全文的重点好不好?毕竟这是Android课的大作业诶。开发工具Android studio,依赖的库比较多,所以代码相当简单。话不多说,开撸了!

应该有哪些界面?

  • SplashActivity(启动页面):展示下logo,还可以做一些耗时操作。
  • LoginActivity(登录页面):用来登录
  • SignupActivity(注册页面):用来注册
  • AnswerActivity(答题页面):答题,上面设置的viewpager绑定的fragment。
  • GradeActivity(得分页面):答题结束后用来展示分数。
  • AnswerFragment:绑定在AnswerActivity之上,根据题目数量动态创建

关系图大概就是下面这个样子。

android 选择题题目 android答题实现 简书_mysql_03

用到了哪些知识?依赖了什么第三方框架?

恩……这部分是写在文档里的,想了想,一并拿出来吧。工程联网部分依赖以okhttp为基础的OkGo框架,数据库部分采用GreenDao框架。其他的,都是特别基础的一些知识,大致如下:

  1. 页面intent跳转,参数的传递
  2. 联网操作以及json数据的解析
  3. sqlite数据库的连接以及增删改查
  4. viewpager与fragment的绑定。
  5. 计时器的设计实现
  6. 主题样式的自定义设置
  7. 自定义对话框
  8. 背景选择器selector的使用
  9. 页面跳转动画效果的设计与实现
  10. listview数据填充及优化

页面详解

BaseActivity(Activity基类)

为了让增强代码可读性,减少重复代码,所以把一些共性代码做了抽取。

public abstract class BaseActivity extends FragmentActivity implements View.OnClickListener {
    @Override
    protected final void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //得到布局文件
        setContentView(getLayoutId());

        //初始化
        initView();
        initData();
        initListener();
    }

    /**
     * @return 布局文件id
     */
    abstract int getLayoutId();

    /**
     * 初始化View
     */
    void initView() {
    }

    /**
     * 初始化界面数据
     */
    void initData() {
    }

    /**
     * 绑定监听器与适配器
     */
    void initListener() {
    }

    /**
     * 对统一的按钮进行统一处理
     *
     * @param v 点击的View
     */
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            default:
                processClick(v);
                break;
        }
    }

    /**
     * 点击事件
     *
     * @param v 点击的View
     */
    void processClick(View v) {
    }
}

SplashActivity(启动页面)

绑定activity_splash布局文件,延时2秒钟跳转主页面。

public class SplashActivity extends BaseActivity {

    @Override
    int getLayoutId() {
        return R.layout.activity_splash;
    }
    @Override
    void initData() {
        //延时2s,跳转。
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                //跳转主页面
                Intent intent = new Intent(SplashActivity.this, MainActivity.class);
                startActivity(intent);
                finish();
            }
        }, 2000);
    }
    
}

LoginActivity(登录页面)

java代码LoginActivity.java

public class LoginActivity extends BaseActivity {
    private static final int REQUEST_SIGNUP = 0;
    EditText et_username;
    EditText et_password;
    Button btn_login;
    TextView tv_signup;

    @Override
    int getLayoutId() {
        return R.layout.activity_login;
    }

    @Override
    void initView() {
        //通过id找控件
        et_username = (EditText) findViewById(R.id.input_username);
        et_password = (EditText) findViewById(R.id.input_password);
        btn_login = (Button) findViewById(R.id.btn_login);
        tv_signup = (TextView) findViewById(R.id.link_signup);
    }

    @Override
    void initListener() {
        //登录按钮,注册链接设置点击监听事件
        btn_login.setOnClickListener(this);
        tv_signup.setOnClickListener(this);
    }

    @Override
    void processClick(View v) {
        switch (v.getId()) {
            //点击登录按钮,执行登录操作
            case R.id.btn_login:
                login();
                break;
            //如果点击了注册链接,则跳转到注册页面
            case R.id.link_signup:
                Intent intent = new Intent(getApplicationContext(), SignupActivity.class);
                startActivityForResult(intent, REQUEST_SIGNUP);
                finish();
                //动画效果
                overridePendingTransition(R.anim.push_left_in, R.anim.push_left_out);
                break;
            default:
                break;
        }
    }

    /**
     * 登录方法
     */
    public void login() {
        //如果内容不合法,则直接返回,显示错误。
        if (!validate()) {
            onLoginFailed();
            return;
        }
        //输入合法,将登录按钮置为不可用,显示圆形进度对话框
        btn_login.setEnabled(false);
        final ProgressDialog progressDialog = new ProgressDialog(LoginActivity.this, R.style.AppTheme_Dark_Dialog);
        progressDialog.setIndeterminate(true);
        progressDialog.setMessage("登录中...");
        progressDialog.show();
        //获取输入内容
        String username = et_username.getText().toString().trim();
        String password = et_password.getText().toString().trim();
        //联网,获取数据
        OkGo.get(CONFIG.URL_LOGIN)
                .params("username", username)
                .params("password", password)
                .execute(new StringCallback() {
                    @Override
                    public void onSuccess(String s, Call call, Response response) {
                        Gson gson = new Gson();
                        JsonLoginBean jsonLoginBean = gson.fromJson(s, JsonLoginBean.class);
                        //如果得到权限>0,则登录成功。
                        if (jsonLoginBean.getPermission() > 0) {
                            Log.e("zwc", "onSuccess: ===");
                            onLoginSuccess();
                            progressDialog.dismiss();
                        } else {
                            onLoginFailed();
                            progressDialog.dismiss();
                        }
                    }
                });
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == REQUEST_SIGNUP) {
            if (resultCode == RESULT_OK) {
                this.finish();
            }
        }
    }

    /**
     * 重写返回键的返回方法
     */
    @Override
    public void onBackPressed() {
        // Disable going back to the MainActivity
        moveTaskToBack(true);
    }

    /**
     * 登录成功
     */
    public void onLoginSuccess() {
        btn_login.setEnabled(true);
        Intent intent = new Intent(LoginActivity.this, MainActivity.class);
        startActivity(intent);
        finish();
    }

    /**
     * 登录失败
     */
    public void onLoginFailed() {
        Toast.makeText(getBaseContext(), "登陆失败", Toast.LENGTH_LONG).show();
        btn_login.setEnabled(true);
    }

    /**
     * @return 判断是否账号密码是否合法
     */
    public boolean validate() {
        //设置初值,默认为合法
        boolean valid = true;

        //获取输入内容
        String email = et_username.getText().toString().trim();
        String password = et_password.getText().toString().trim();

        //判断账号
        if (email.isEmpty()) {
            et_username.setError("请输入你的账号");
            valid = false;
        } else {
            et_username.setError(null);
        }
        //判断密码
        if (password.isEmpty()) {
            et_password.setError("请输入你的密码");
            valid = false;
        } else {
            et_password.setError(null);
        }

        return valid;
    }
}

布局文件activity_login.xml

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:fitsSystemWindows="true">
    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingTop="56dp"
        android:paddingLeft="24dp"
        android:paddingRight="24dp">

        <ImageView android:src="@drawable/logo"
            android:layout_width="wrap_content"
            android:layout_height="72dp"
            android:layout_marginBottom="24dp"
            android:layout_gravity="center_horizontal" />

        <!--  账号 -->
        <android.support.design.widget.TextInputLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="8dp"
            android:layout_marginBottom="8dp">
            <EditText
                android:id="@+id/input_username"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:inputType="number"
                android:hint="账号" />
        </android.support.design.widget.TextInputLayout>

        <!-- 密码 -->
        <android.support.design.widget.TextInputLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="8dp"
            android:layout_marginBottom="8dp">
            <EditText android:id="@+id/input_password"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:inputType="textPassword"
                android:hint="密码"/>
        </android.support.design.widget.TextInputLayout>

        <android.support.v7.widget.AppCompatButton
            android:id="@+id/btn_login"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="24dp"
            android:layout_marginBottom="24dp"
            android:padding="12dp"
            android:text="登录"/>

        <TextView android:id="@+id/link_signup"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="24dp"
            android:text="没有账号?创建一个"
            android:gravity="center"
            android:textSize="16dip"/>
    </LinearLayout>
</ScrollView>

SignupActivity(注册页面)

SignupActivity.java

public class SignupActivity extends BaseActivity {

    EditText _nameText;
    EditText _emailText;
    EditText _passwordText;
    EditText _reEnterPasswordText;
    Button _signupButton;
    TextView _loginLink;

    @Override
    int getLayoutId() {
        return R.layout.activity_signup;
    }

    @Override
    void initView() {
        //根据id找控件
        _nameText = (EditText) findViewById(R.id.input_name);
        _emailText = (EditText) findViewById(R.id.input_username);
        _passwordText = (EditText) findViewById(R.id.input_password);
        _reEnterPasswordText = (EditText) findViewById(R.id.input_reEnterPassword);
        _signupButton = (Button) findViewById(R.id.btn_signup);
        _loginLink = (TextView) findViewById(R.id.link_login);
        _signupButton.setOnClickListener(this);
        _loginLink.setOnClickListener(this);
    }

    @Override
    void processClick(View v) {
        switch (v.getId()) {
            case R.id.btn_signup:
                signup();
                break;
            case R.id.link_login:
                //点击登录连接,跳转到登录页面
                Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
                startActivity(intent);
                finish();
                overridePendingTransition(R.anim.push_left_in, R.anim.push_left_out);
                break;
            default:
                break;
        }
    }

    public void signup() {
        //判断是否合法
        if (!validate()) {
            onSignupFailed(0);
            return;
        }
        _signupButton.setEnabled(false);

        //显示圆形进度条对话框
        final ProgressDialog progressDialog = new ProgressDialog(SignupActivity.this,
                R.style.AppTheme_Dark_Dialog);
        progressDialog.setIndeterminate(true);
        progressDialog.setMessage("创建账号...");
        progressDialog.show();
        //获取数据
        String username = _nameText.getText().toString();
        String password = _passwordText.getText().toString();
//      联网获取数据
        OkGo.get(CONFIG.URL_SIGNUP)
                .params("username", username)
                .params("password", password)
                .execute(new StringCallback() {
                    @Override
                    public void onSuccess(String s, Call call, Response response) {
                        Gson gson = new Gson();
                        JsonSignupBean jsonSignupBean = gson.fromJson(s, JsonSignupBean.class);
                        //如果得到返回消息为ok,则注册成功。
                        if (jsonSignupBean.getMsg().equals("ok")) {
                            Log.e("zwc", "onSuccess: 注册成功");
                            onSignupSuccess();
                            //对话框消失
                            progressDialog.dismiss();
                        } else {
                            onSignupFailed(1);
                            progressDialog.dismiss();
                        }
                    }
                });
    }

    /**
     * 登陆成功
     */
    public void onSignupSuccess() {
        _signupButton.setEnabled(true);

        Intent intent = new Intent(SignupActivity.this, MainActivity.class);
        startActivity(intent);
        finish();
    }

    /**
     * 注册失败,按钮置为可用
     * 依据传参不同,进行不同吐司
     */
    public void onSignupFailed(int i) {
        if (i == 1) {
            Toast.makeText(getBaseContext(), "该用户名已经被注册", Toast.LENGTH_LONG).show();
        } else {
            Toast.makeText(getBaseContext(), "注册失败", Toast.LENGTH_LONG).show();
        }
        _signupButton.setEnabled(true);
    }

    /**
     * @return 输入内容是否合法
     */
    public boolean validate() {
        boolean valid = true;
		//从控件中获取数据
        String name = _nameText.getText().toString();
        String password = _passwordText.getText().toString();
        String reEnterPassword = _reEnterPasswordText.getText().toString();
        //检测账号是否正确
        if (name.isEmpty()) {
            _nameText.setError("账号不能为空");
            valid = false;
        } else {
            _nameText.setError(null);
        }
        //检测密码是否正确
        if (password.isEmpty()) {
            _passwordText.setError("请输入密码");
            valid = false;
        } else {
            _passwordText.setError(null);
        }
        //检测重复密码是否正确
        if (reEnterPassword.isEmpty() || !(reEnterPassword.equals(password))) {
            _reEnterPasswordText.setError("两次密码不一致");
            valid = false;
        } else {
            _reEnterPasswordText.setError(null);
        }
        return valid;
    }
}

布局文件 activity_signup.xml

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:fitsSystemWindows="true">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:paddingLeft="24dp"
        android:paddingRight="24dp"
        android:paddingTop="56dp">

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="72dp"
            android:layout_gravity="center_horizontal"
            android:layout_marginBottom="24dp"
            android:src="@drawable/logo" />

        <!-- 账号 -->
        <android.support.design.widget.TextInputLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="8dp"
            android:layout_marginTop="8dp">

            <EditText
                android:id="@+id/input_name"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="账号"
                android:inputType="textPersonName" />
        </android.support.design.widget.TextInputLayout>

        <!-- 密码 -->
        <android.support.design.widget.TextInputLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="8dp"
            android:layout_marginTop="8dp">

            <EditText
                android:id="@+id/input_password"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="密码"
                android:inputType="textPassword" />
        </android.support.design.widget.TextInputLayout>

        <!-- 重复密码 -->
        <android.support.design.widget.TextInputLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="8dp"
            android:layout_marginTop="8dp">

            <EditText
                android:id="@+id/input_reEnterPassword"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="重复密码"
                android:inputType="textPassword" />
        </android.support.design.widget.TextInputLayout>

        <android.support.v7.widget.AppCompatButton
            android:id="@+id/btn_signup"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="24dp"
            android:layout_marginTop="24dp"
            android:padding="12dp"
            android:text="创建账号" />

        <TextView
            android:id="@+id/link_login"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="24dp"
            android:gravity="center"
            android:text="已有账号?马上登陆"
            android:textSize="16dip" />

    </LinearLayout>
</ScrollView>

AnswerActivity ,AnswerFragment(答题页面)

回答问题的页面。当到达AnswerActivity页面的时候,会联网获取题目数据,并将题目存入本地数据库。然后通过viewpager绑定n个AnswerFragment,对题目进行展示。作答后,进行存库操作。(n由题目数量决定)

public class AnswerActivity extends BaseActivity implements Chronometer.OnChronometerTickListener {

    private Chronometer chronometer;
    private ViewPager vp_answer;
    private ArrayList<Fragment> fragmentlists;
    private int minute = 0;
    private int second = 0;
    private AlertDialog.Builder builder;
    private ArrayList<String> a;
    private Button btn_previous;
    private Button btn_submit;
    private Button btn_next;
    private int nowpager = 0;
    private List<QuestBean> messages;
    private String type;

    @Override
    int getLayoutId() {
        return R.layout.activity_answer;
    }

    /**
     * 初始化布局
     */
    @Override
    void initView() {
        chronometer = (Chronometer) findViewById(R.id._chro_exam);
        vp_answer = (ViewPager) findViewById(R.id.vp_answer);
        btn_previous = (Button) findViewById(R.id._btn_previous);
        btn_submit = (Button) findViewById(R.id._btn_submit);
        btn_next = (Button) findViewById(R.id._btn_next);
//        获取传递来的变量
        type = getIntent().getExtras().get("type").toString().trim();

//      联网获取数据
        initNet(type);

        btn_previous.setOnClickListener(this);
        btn_submit.setOnClickListener(this);
        btn_next.setOnClickListener(this);
        vp_answer.setOnPageChangeListener(new MyOnPageChangeListener());
        setChronometer();
    }

    /**
     * 设置计时器
     */
    private void setChronometer() {
        chronometer.setText(nowtime());
        chronometer.start();
        chronometer.setOnChronometerTickListener(this);
        chronometer.setOnClickListener(this);
    }

    /**
     * 计时器规则
     *
     * @param chronometer
     */
    @Override
    public void onChronometerTick(Chronometer chronometer) {
        second++;
        if (second == 59) {
            minute++;
            second = 00;
        }
    }

    /**
     * 现在时间
     *
     * @return
     */
    private String nowtime() {
        if (second < 10) {
            return (minute + ":0" + second);
        } else {
            return (minute + ":" + second);
        }
    }

    /**
     * 初始化网络连接
     * @param type
     */
    private void initNet(String type) {
        a = new ArrayList<>();
        fragmentlists = new ArrayList<>();
        //进度条对话框
        final ProgressDialog progressDialog = new ProgressDialog(AnswerActivity.this, R.style.AppTheme_Dark_Dialog);
        progressDialog.setIndeterminate(true);
        progressDialog.setMessage("获取题目中...");
        progressDialog.show();
//        联网
        OkGo.get(CONFIG.URL_GETQUEST1)
                .params("type", type)
                .execute(new StringCallback() {
                    @Override
                    public void onSuccess(String s, Call call, Response response) {
                        //gson解析
                        Gson gson = new Gson();
                        JsonQuestBean jsonQuestBean = gson.fromJson(s, JsonQuestBean.class);
                        messages = jsonQuestBean.getMessages();
                        for (int i = 0; i < messages.size(); i++) {
                            QuestBean questBeanQ = messages.get(i);
                            questBeanQ.setId(i);
                            fragmentlists.add(new AnswerFragment(questBeanQ));
                            LoveDao.insertLove(questBeanQ);
                            a.add(questBeanQ.getId() + "");
                        }
//                        设置适配器
                        vp_answer.setAdapter(new MainAdapter(getSupportFragmentManager()));
                        progressDialog.dismiss();
                    }

                    @Override
                    public void onError(Call call, Response response, Exception e) {
                    }
                });
    }

    /**
     * viewpager适配器
     */
    class MainAdapter extends FragmentPagerAdapter {

        public MainAdapter(FragmentManager fm) {
            super(fm);
        }

        //获取条目
        @Override
        public Fragment getItem(int position) {
            return fragmentlists.get(position);
        }

        //数目
        @Override
        public int getCount() {
            return fragmentlists.size();
        }
    }

    @Override
    void processClick(View v) {
        switch (v.getId()) {
//            点击上一题按钮
            case R.id._btn_previous:
//                如果是第一题,则谈吐司提醒,否则上移一道题
                if (nowpager == 0) {
                    Toast.makeText(AnswerActivity.this, "已经到头啦!", Toast.LENGTH_SHORT).show();
                } else {
                    vp_answer.setCurrentItem(--nowpager);
                }
                break;
//            点击提交按钮
            case R.id._btn_submit:
//                简答题不进行提交评分
                if (type.equals("3")) {
                    Toast.makeText(this, "简答题目前暂不支持评分", Toast.LENGTH_SHORT).show();
                    return;
                }
//                否则初始化并展示提交对话框
                initAlertDialog();
                builder.show();
                break;
//            点击下一题按钮
            case R.id._btn_next:
//                如果是最后一题,则谈吐司提醒,否则下移一道题
                if (nowpager == fragmentlists.size()) {
                    Toast.makeText(AnswerActivity.this, "已经是最后一题了!", Toast.LENGTH_SHORT).show();
                } else {
                    vp_answer.setCurrentItem(++nowpager);
                }
                break;
            default:
                break;
        }
    }

    // 弹出是否确认交卷的对话框
    private void initAlertDialog() {
        //新建对话框
        builder = new AlertDialog.Builder(AnswerActivity.this);
        builder.setTitle("提示");
        builder.setMessage("是否确定交卷?");
        builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                // TODO: 2017/6/14 交卷操作
//                计算分数
                int grade = 0;
//                判断题
                if (type.equals("2")) {
                    for (int i = 0; i < messages.size(); i++) {
//                        查询
                        QuestBean questBeenA = LoveDao.queryLove(Integer.parseInt(a.get(i)));
//                        判断
                        if (questBeenA.getAnswer().equals("对") && questBeenA.getMyanswer().equals("A") || questBeenA.getAnswer().equals("错") && questBeenA.getMyanswer().equals("B")) {
                            grade += 20;
                        }
                        ;
                    }
                }
//                选择题
                else {
                    for (int i = 0; i < messages.size(); i++) {
                        QuestBean questBeenA = LoveDao.queryLove(Integer.parseInt(a.get(i)));
                        if (questBeenA.getAnswer().equals(questBeenA.getMyanswer())) {
                            grade += 20;
                        }
                        ;
                    }
                }

//                传递分数
                Intent intent = new Intent(AnswerActivity.this, GradeActivity.class);
                intent.putExtra("grade", "" + grade);
//                传递题目列表
                intent.putStringArrayListExtra("timu", a);
                startActivity(intent);
                finish();
            }

        });
        builder.setNegativeButton("取消", null);
    }

    /**
     * viewpager监听事件
     */
    private class MyOnPageChangeListener implements ViewPager.OnPageChangeListener {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        }

        @Override
        public void onPageSelected(int position) {
            nowpager = position;
        }

        @Override
        public void onPageScrollStateChanged(int state) {

        }
    }

恩,现在就写了这么多,对于作业来说应该是够了。不过还是有很多需要改善的地方。以后有时间的话,会继续完善一下。最后,本文挺长的。真诚的感谢一下你能看到这里。