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ữ fileData
và gọi phương thứcaddQuestions()
.
- Nhận đường dẫn dữ liệu kiểu
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.
- Khai báo class xử lý dữ liệu và
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:
- Ánh xạ dữ liệu với Interface (Đã hoàn thành)
- Khai báo và xử lý dữ liệu.
- 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>