Search…

Sử Dụng CSDL Hướng Đối Tượng DB4O với Android - Phần 2

08/11/20207 min read
Hướng dẫn xây dựng một chương trình trắc nghiệm đơn giản sử dụng hệ quản trị cơ sở dữ liệu DB4O trên Android

Bài viết hướng dẫn xây dựng một chương trình trắc nghiệm đơn giản.

Xây dựng Layout

Đầu tiên cần xác định giao diện chính cho ứng dụng. Ở đây xây dựng một layout đơn giản phục vụ cho công việc hiển thị dữ liệu trắc nghiệm.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:weightSum="1">


<TextView
    android:text="SAMPLE"
    android:layout_width="match_parent"
    android:id="@+id/txtSample"
    android:layout_height="80dp" />

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

    <ImageView
        app:srcCompat="@mipmap/ic_launcher"
        android:id="@+id/imgIcon"
        android:layout_weight="1"
        android:layout_height="150dp"
        android:layout_width="60dp" />

    <TextView
        android:text="Question"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:id="@+id/txtQuestion"
        android:layout_weight="1" />

</LinearLayout>

<RadioGroup
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/radioGroup1">

    <RadioButton
        android:text="A"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/radioButton1"
        android:layout_weight="1" />

    <RadioButton
        android:text="B"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/radioButton2"
        android:layout_weight="1" />

    <RadioButton
        android:text="C"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/radioButton3"
        android:layout_weight="1" />

    <RadioButton
        android:text="D"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/radioButton4"
        android:layout_weight="1" />
</RadioGroup>

<Button
    android:text="Chọn"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/btnChoose" />

</LinearLayout>

Bước tiếp theo là ánh xạ dữ liệu này lên class xử lý. Trong trường hợp này là class MainActivity.

Bước này rất quan trọng và nên làm đầu tiên. Vì sau khi chương trình trở nên lớn và phức tạp thì rất dễ sai ở bước này, và chương trình sẽ hoàn toàn không báo lỗi.

Khi các giao thức vô tình gọi đến các Item chưa được ánh xạ thì chương trình không thể thực thi. 

public class MainActivity extends AppCompatActivity {

    TextView txtQuestion;
    TextView txtSample;
    RadioButton rda, rdb, rdc, rdd;
    Button btnChoose;

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

        // mappings with interface
        txtQuestion = (TextView) findViewById(R.id.txtQuestion);
        txtSample = (TextView) findViewById(R.id.txtSample);
        rda = (RadioButton) findViewById(R.id.radioButton1);
        rdb = (RadioButton) findViewById(R.id.radioButton2);
        rdc = (RadioButton) findViewById(R.id.radioButton3);
        rdd = (RadioButton) findViewById(R.id.radioButton4);
        btnChoose = (Button) findViewById(R.id.btnChoose); 
        Log.e("mapping interface: ", "OK " );

    }
}

Xây dựng class xử lý dữ liệu

Xây dựng class Question với các thành phần như sau:

public class Question {
    public int ID;
    public String SAMPLE;
    public String QUESTION;
    public String ANSWER;
    public String OPTA;
    public String OPTB;
    public String OPTC;
    public String OPTD;
}

Tiếp theo bấm chuột phải để sử dụng các giao thức (Constructor, getter and setter) trong Generate. Sau khi sử dụng giao thức có class Question như sau: 

public class Question {
    public int ID;
    public String SAMPLE;
    public String QUESTION;
    public String ANSWER;
    public String OPTA;
    public String OPTB;
    public String OPTC;
    public String OPTD;

    public Question(){}

    public Question(int ID, String SAMPLE, String QUESTION, String ANSWER, String OPTA, String OPTB, String OPTC, String OPTD) {
        this.ID = ID;
        this.SAMPLE = SAMPLE;
        this.QUESTION = QUESTION;
        this.ANSWER = ANSWER;
        this.OPTA = OPTA;
        this.OPTB = OPTB;
        this.OPTC = OPTC;
        this.OPTD = OPTD;
    }

    public int getID() {
        return ID;
    }

    public void setID(int ID) {
        this.ID = ID;
    }

    public String getSAMPLE() {
        return SAMPLE;
    }

    public void setSAMPLE(String SAMPLE) {
        this.SAMPLE = SAMPLE;
    }

    public String getQUESTION() {
        return QUESTION;
    }

    public void setQUESTION(String QUESTION) {
        this.QUESTION = QUESTION;
    }

    public String getANSWER() {
        return ANSWER;
    }

    public void setANSWER(String ANSWER) {
        this.ANSWER = ANSWER;
    }

    public String getOPTA() {
        return OPTA;
    }

    public void setOPTA(String OPTA) {
        this.OPTA = OPTA;
    }

    public String getOPTB() {
        return OPTB;
    }

    public void setOPTB(String OPTB) {
        this.OPTB = OPTB;
    }

    public String getOPTC() {
        return OPTC;
    }

    public void setOPTC(String OPTC) {
        this.OPTC = OPTC;
    }

    public String getOPTD() {
        return OPTD;
    }

    public void setOPTD(String OPTD) {
        this.OPTD = OPTD;
    }
}

Xây dựng class xử lý dữ liệu DbHelper

Đối với một chương trình việc sử dụng và xử lý dữ liệu rất phức tạp, không thể lúc nào cũng xử lý tất cả trong 1 class. Class DbHelper được xây dựng để xử lý các dữ liệu các dữ liệu theo thư viện DB4O.

Trong Class xây dựng 3 phương thức:

  • public DbHelper(String dbPath);
    • Nhận đường dẫn dữ liệu kiểu String, khởi tạo dữ file Data và gọi phương thức addQuestions().
  • addQuestions();
    • Khai báo class xử lý dữ liệu và add vào db. Trong class này chỉ add mẫu 2 dữ liệu.
  • List<Question> getAllQuestions();
    • Giao thức này trả về danh sách dữ liệu.

Class DbHelper tổng quát

import android.support.v7.app.AppCompatActivity;
import android.util.Log;

import com.db4o.Db4oEmbedded;
import com.db4o.ObjectContainer;
import com.db4o.ObjectSet;

import java.util.ArrayList;
import java.util.List;

public class DbHelper {
      ObjectContainer db;

public DbHelper(String dbPath) {
        db = Db4oEmbedded.openFile(Db4oEmbedded.newConfiguration(), dbPath);
        addQuestions();
    }

 private void addQuestions() { //---- Chèn dữ liệu - Insert  Database
        Question q1=new Question(1,"The CPU is large chip …………… the computer",
                "","INSIDE","ONTO","OUE","FROM","INSIDE");
        db.store(q1);
        Question q2=new Question(2,"Data always flows …………. The CPU …………The address bus",
                "","FROM/TO","FROM/TO","TO/TO","TO/FROM","ONTO/FROM");
        db.store(q2);

        Log.e(" AddQuestions: ", "OK " );
    }

 public List<Question> getAllQuestions(){ //----add questions to list

        List<Question> quesList = new ArrayList<Question>();

        try{
            //----Search all QBE----
            Question question = new Question();
            ObjectSet<Question> questions = db.queryByExample(question);
            for (Question quest:questions){
                quesList.add(quest);
                Log.e("Quest value: ", quest.getANSWER());
            }
        }finally{
            db.close();
        }
        Log.e("Test get all Questions: ", "OK " );
        return quesList;
    }

}

Xây dựng MainActivity

Class này có 3 phần chính:

  1. Ánh xạ dữ liệu với Interface (Đã hoàn thành)
  2. Khai báo và xử lý dữ liệu.
  3. Viết xử lý ứng dụng. 

Khai báo và xử lý dữ liệu: tạo giao thức setQuestionView( ){ } để lấy thông tin và chuyển lên interface. Trong giao thức này viết các hàm Log để kiểm tra dữ liệu.

Xử lý ứng dụng: tại button choose gọi sự kiện setOnClickListener(). Khai báo tính điểm đơn giản và khai báo điều kiện và intent để chuyển sang class ResultActivity

Class MainActivity tổng quát

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TextView;

import java.util.List;

public class MainActivity extends AppCompatActivity {
    List<Question> quesList;
    int score=0;
    int qid=0;
    Question currentQ;
    TextView txtCheck;
    TextView txtQuestion;
    TextView txtSample;
    RadioButton rda, rdb, rdc, rdd;
    Button btnChoose;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Mappings with interface
        txtQuestion = (TextView) findViewById(R.id.txtQuestion);
        txtSample = (TextView) findViewById(R.id.txtSample);
        rda = (RadioButton) findViewById(R.id.radioButton1);
        rdb = (RadioButton) findViewById(R.id.radioButton2);
        rdc = (RadioButton) findViewById(R.id.radioButton3);
        rdd = (RadioButton) findViewById(R.id.radioButton4);
        btnChoose = (Button) findViewById(R.id.btnChoose);
        Log.e("mapping interface: ", "OK " );

        // Create the DB:
        String dbPath =  "/data/data/" + getPackageName() + "/Db4oDatabase.db4o";
        Log.e("String Data Main: ",dbPath);
        //ObjectContainer db = Db4oEmbedded.openFile(Db4oEmbedded.newConfiguration(), dbPath);

        DbHelper data =new DbHelper(dbPath);
        quesList=data.getAllQuestions();
        currentQ=quesList.get(qid);
        setQuestionView();

        // Game Play
        btnChoose.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {


                RadioGroup grp=(RadioGroup) findViewById(R.id.radioGroup1);
                RadioButton answer=(RadioButton)findViewById(grp.getCheckedRadioButtonId());
                Log.e("Check answer: ", currentQ.getANSWER()+" "+answer.getText());
                if(currentQ.getANSWER().equals(answer.getText()))
                {
                    score++;
                    Log.d("score", "Your score"+score);
                }
                if(qid<5){
                    currentQ=quesList.get(qid);
                    setQuestionView();
                }else{
                    Log.e("Check Intent: ", "Begin ... " );
                    Intent intent = new Intent(MainActivity.this, ResultActivity.class);
                    Log.e("Check Intent: ", "Set Intent " );
                    Bundle b = new Bundle();
                    b.putInt("score", score); //Your score
                    intent.putExtras(b); //Put your score to your next Intent
                    Log.e("Check Intent: ", "PutExtras OK " );
                    startActivity(intent);
                    Log.e("Check Intent: ", "Start Activity intent " );
                    finish();
                }
            }
        });
    }

    private void setQuestionView() { // -- set value for interface

        Log.e("Set QuestionView: ", "Begin ...  " );
        txtQuestion.setText(currentQ.getQUESTION());
        Log.e("Set QuestionView: ", "Question value: " + currentQ.getQUESTION());
        txtSample.setText(currentQ.getSAMPLE());
        Log.e("Set QuestionView: ", "Sample value: " + currentQ.getSAMPLE());
        rda.setText(currentQ.getOPTA());
        Log.e("Set QuestionView: ", "A value: " + currentQ.getOPTA());
        rdb.setText(currentQ.getOPTB());
        Log.e("Set QuestionView: ", "B value: " + currentQ.getOPTB());
        rdc.setText(currentQ.getOPTC());
        Log.e("Set QuestionView: ", "C value: " + currentQ.getOPTC());
        rdd.setText(currentQ.getOPTD());
        Log.e("Set QuestionView: ", "D value: " + currentQ.getOPTD());
        qid++;
        Log.e("Set QuestionView: ", "End -- OK " );
    }
}

Xây dựng Class ResultActivity

Trong Class này cần xây dựng một giao diện layout đơn giản để hiển thị điểm và 1 button để trả về class MainActivity.

Layout activity_result

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:text="Score"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/txtScore" />

    <Button
        android:text="Return"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/btnReturn" />
</LinearLayout>

Class ResultActivity

public class ResultActivity extends AppCompatActivity{

    TextView txtScore;
    Button btnReturn;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_result);
        // mapping to interface
        txtScore = (TextView) findViewById(R.id.txtScore);
        btnReturn = (Button) findViewById(R.id.btnReturn);
        Log.e("Check Result Activity: ", "mapping to interface OK " );
        //get score
        Bundle b = getIntent().getExtras();
        int score= b.getInt("score");
        Log.e("Check Result Activity: ", "get score: "+ score );
        // show
        txtScore.setText("score: "+ score);
        Log.e("Check Result Activity: ", "show scre: "+ score );

        btnReturn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(ResultActivity.this, MainActivity.class );
                startActivity(intent);
                finish();
            }
        });
    }
}

AndroidManifest 

Thêm thẻ

<activity android:name=".ResultActivity"></activity>

Bài chung series

IO Stream

IO Stream Co., Ltd

30 Trinh Dinh Thao, Hoa Thanh ward, Tan Phu district, Ho Chi Minh city, Vietnam
+84 28 22 00 11 12
developer@iostream.co

383/1 Quang Trung, ward 10, Go Vap district, Ho Chi Minh city
Business license number: 0311563559 issued by the Department of Planning and Investment of Ho Chi Minh City on February 23, 2012

©IO Stream, 2013 - 2024