安卓使用网络技术实战——简易的在线考试app
文章目录
- 一、实现内容
- 二、用到的部分知识点及参考
- 1.实现界面跳转并传递数据——使用Intent
- 2.控件的隐藏与显示
- 3.通过Handler把需要在另一个线程执行的操作加入到消息队列中去
- 4.使用okHttp解析XML文件
- 5.单选项——使用RadioGroup和RadioButton并获取用户选中值
- 三、效果图
- 四、完整代码
- 1.服务器端.xml文件
- 2.添加okhttp依赖
- 3.布局文件——activity_main.xml(使用ScrollView)
- 4.MainActivity.java
- 5.AndroidManifect.xml——加入网络权限的申请
- 6.新的Activity—ResultActivity.java
- 7.activity_result.xml
一、实现内容
1、搭建一个简单的服务器,将考试题目和答案以XML格式存放在服务器上(5题,每题20分);
2、应用程序的启动界面有一个按钮,点击按钮开始考试,同时发送HTTP请求,对XML格式数据进行解析,显示出来;
3、用户根据题目答题;
4、完成全部题目后,根据答题情况给用户打分,如果小于80分(每小题20分),判定为考试不合格,用户可以选择重新考试;
二、用到的部分知识点及参考
1.实现界面跳转并传递数据——使用Intent
界面跳转一般是这样的:(示例是从FirstActivity跳转到SecondActivity)
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
startActivity(intent);
如何传递数据?使用putExtra()函数
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
intent.putExtra("name",xxx);
startActivity(intent);
接收数据:
// 首先获取到意图对象
Intent intent = getIntent();
// 获取到传递过来的姓名
String xxx = intent.getStringExtra("name");
还可以传递图片等复杂数据的,在这里先不作讨论。
2.控件的隐藏与显示
可见(visible)
XML文件:android:visibility=“visible”
Java代码:view.setVisibility(View.VISIBLE);
不可见(invisible)
XML文件:android:visibility=“invisible”
Java代码:view.setVisibility(View.INVISIBLE);
隐藏(GONE)
XML文件:android:visibility=“gone”
Java代码:view.setVisibility(View.GONE);
隐藏和不可见的区别:
不可见会让view看不见,但是实际还在那里,隐藏会让view整个移除,实际不在那里(不占位)
另:隐藏和不可见设置都会使控件的点击事件失效,也就是无法点击
3.通过Handler把需要在另一个线程执行的操作加入到消息队列中去
如果不使用handler就直接在子线程中setText,则会报错,因为android中相关的view和控件不是线程安全的,我们必须单独做处理。
(下面这段代码是放在子线程的run函数下面的)
// 在子线程中实例化Handler同样是可以的,只要在构造函数的参数中传入主线程的Looper即可Handler handler = new Handler(Looper.getMainLooper());// 通过Handler的post Runnable到UI线程的MessageQueue中去即可handler.post(new Runnable() {@Overridepublic void run() {// 在MessageQueue出队该Runnable时进行的操作int quesCount = 0;for(Question aQues:questions) {ques_title[quesCount].setText(aQues.getTitle());quesRadioButton[quesCount].setText(aQues.getChoiceA());quesRadioButton[quesCount + 5].setText(aQues.getChoiceB());if(!aQues.getChoiceC().equals("")){quesRadioButton[quesCount + 10].setText(aQues.getChoiceC());quesRadioButton[quesCount + 15].setText(aQues.getChoiceD());}ques_group[quesCount].setVisibility(View.VISIBLE);quesCount++;}}});
关于Handler的用法可以参考:Android基础夯实–你了解Handler有多少?
4.使用okHttp解析XML文件
这里是参考了安卓开发之解析XML和JSON格式数据
感觉网络这一块他讲得很清楚了,这里就不多赘述。
不过他是用的apache作服务端,我因为本身就有javaEE开发经验,所以是直接使用了eclipse用tomcat了,这样也可以的哈。
然后解释一下为什么要开一个新线程:
在Android4.0以后,在主线程中的HTTP请求,运行时都会报错 ANRs (“Application Not Responding”),”应用没有响应“。
所以当进行网络请求的时候 还是需要开辟一个子线程,然后等到数据返回成功后再刷新UI。
5.单选项——使用RadioGroup和RadioButton并获取用户选中值
单选的话就是用RadioGroup和RadioButton,每个RadioGroup下有多个RadioButton,但只有一个能够被选中。
获取用户的值方法1:使用setOnCheckedChangeListener监听
radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {@Overridepublic void onCheckedChanged(RadioGroup group, int checkedId) {int id = group.getCheckedRadioButtonId();RadioButton radioBtn = MainActivity.this.findViewById(id);String text = radioBtn.getText().toString();}
});
获取用户值方法2:对radiogroup中组件进行循环,依次判断组件是否isChecked,从而找到选中的组件
//该RadioGroup下有几个RadioButon
int count = radioGroup.getChildCount();
//遍历RadioButon
for(int j = 0 ;j < count;j++){RadioButton rb = (RadioButton)radioGroup.getChildAt(j);if(rb.isChecked()){String text = rb.getText().toString();//userAnswer[i] = text.split("\\.")[0];//这里是进行了分割然后存入了答案数组}
}
三、效果图
打开app: 点击开始考试后:
提交试卷:<80不合格,>=80合格
四、完整代码
1.服务器端.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<questions><question><id>1</id><title>驾驶机动车在道路上违反道路交通安全法的行为,属于什么行为?</title><choiceA>违章行为</choiceA><choiceB>违法行为</choiceB><choiceC>过失行为</choiceC><choiceD>违规行为</choiceD><answer>B</answer></question><question><id>2</id><title>机动车驾驶人违法驾驶造成重大交通事故构成犯罪的,依法追究什么责任?</title><choiceA>刑事责任</choiceA><choiceB>民事责任</choiceB><choiceC>经济责任</choiceC><choiceD>直接责任</choiceD><answer>A</answer></question><question><id>3</id><title>机动车驾驶人造成事故后逃逸构成犯罪的,吊销驾驶证且多长时间不得重新取得驾驶证?</title><choiceA>5年内</choiceA><choiceB>10年内</choiceB><choiceC>终生</choiceC><choiceD>20年内</choiceD><answer>C</answer></question><question><id>4</id><title>驾驶机动车违反道路交通安全法律法规发生交通事故属于交通违章行为。</title><choiceA>正确</choiceA><choiceB>错误</choiceB><answer>B</answer></question><question><id>5</id><title>驾驶机动车在道路上违反道路通行规定应当接受相应的处罚。</title><choiceA>正确</choiceA><choiceB>错误</choiceB><answer>A</answer></question></questions>
2.添加okhttp依赖
在app下的build.gradle文件中:
dependencies{implementation 'com.squareup.okhttp3:okhttp:3.13.1'
}
如果添加依赖出现问题,则参考解决无法添加okhttp依赖的问题(Could not resolve com.sqaureup.okhttp3:okhttp:3.x.x)
3.布局文件——activity_main.xml(使用ScrollView)
主要就是一个按钮和一个ScrollView
ScrollView控件可以以滚动的形式查看屏幕外部分的内容
ScrollView只能包含一个子视图或视图组,在实际项目中,通常包含的是一个垂直的LinearLayout
ScrollView是一个滚动视图的容器,对于一些自带了滚动效果的控件必须ListView,是无法和它一起被混合使用的
还有一点就是ScrollView只能有一个孩子,也就是说直接把很多个RadioGroup放在它下面是不行的,一定要先在多个RadioGroup外面套一个比如LinearLayout。
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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"tools:context=".MainActivity"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><Buttonandroid:id="@+id/send_request"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="开始考试"/><!--ScrollView控件可以以滚动的形式查看屏幕外部分的内容ScrollView只能包含一个子视图或视图组,在实际项目中,通常包含的是一个垂直的LinearLayoutScrollView是一个滚动视图的容器,对于一些自带了滚动效果的控件必须ListView,是无法和它一起被混合使用的--><ScrollViewandroid:layout_width="match_parent"android:layout_height="match_parent"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"><TextViewandroid:id="@+id/ques_title1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="10dp"android:textSize="18dp"android:layout_marginTop="20dp"/><RadioGroupandroid:id="@+id/ques_choices1"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"android:visibility="invisible"><RadioButtonandroid:id="@+id/choiceA1"android:layout_width="match_parent"android:layout_height="wrap_content"android:textSize="16sp"/><RadioButtonandroid:id="@+id/choiceB1"android:layout_width="match_parent"android:layout_height="wrap_content"android:textSize="16sp" /><RadioButtonandroid:id="@+id/choiceC1"android:layout_width="match_parent"android:layout_height="wrap_content"android:textSize="16sp" /><RadioButtonandroid:id="@+id/choiceD1"android:layout_width="match_parent"android:layout_height="wrap_content"android:textSize="16sp" /></RadioGroup><TextViewandroid:id="@+id/ques_title2"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="10dp"android:textSize="18dp"android:layout_marginTop="20dp"/><RadioGroupandroid:id="@+id/ques_choices2"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"android:visibility="invisible"><RadioButtonandroid:id="@+id/choiceA2"android:layout_width="match_parent"android:layout_height="wrap_content"android:textSize="16sp" /><RadioButtonandroid:id="@+id/choiceB2"android:layout_width="match_parent"android:layout_height="wrap_content"android:textSize="16sp" /><RadioButtonandroid:id="@+id/choiceC2"android:layout_width="match_parent"android:layout_height="wrap_content"android:textSize="16sp" /><RadioButtonandroid:id="@+id/choiceD2"android:layout_width="match_parent"android:layout_height="wrap_content"android:textSize="16sp" /></RadioGroup><TextViewandroid:id="@+id/ques_title3"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="10dp"android:textSize="18dp"android:layout_marginTop="20dp"/><RadioGroupandroid:id="@+id/ques_choices3"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"android:visibility="invisible"><RadioButtonandroid:id="@+id/choiceA3"android:layout_width="match_parent"android:layout_height="wrap_content"android:textSize="16sp" /><RadioButtonandroid:id="@+id/choiceB3"android:layout_width="match_parent"android:layout_height="wrap_content"android:textSize="16sp" /><RadioButtonandroid:id="@+id/choiceC3"android:layout_width="match_parent"android:layout_height="wrap_content"android:textSize="16sp" /><RadioButtonandroid:id="@+id/choiceD3"android:layout_width="match_parent"android:layout_height="wrap_content"android:textSize="16sp" /></RadioGroup><TextViewandroid:id="@+id/ques_title4"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="10dp"android:textSize="18dp"android:layout_marginTop="20dp"/><RadioGroupandroid:id="@+id/ques_choices4"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"android:visibility="invisible"><RadioButtonandroid:id="@+id/choiceA4"android:layout_width="match_parent"android:layout_height="wrap_content"android:textSize="16sp" /><RadioButtonandroid:id="@+id/choiceB4"android:layout_width="match_parent"android:layout_height="wrap_content"android:textSize="16sp" /></RadioGroup><TextViewandroid:id="@+id/ques_title5"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="10dp"android:textSize="18dp"android:layout_marginTop="20dp"/><RadioGroupandroid:id="@+id/ques_choices5"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"android:visibility="invisible"><RadioButtonandroid:id="@+id/choiceA5"android:layout_width="match_parent"android:layout_height="wrap_content"android:textSize="16sp" /><RadioButtonandroid:id="@+id/choiceB5"android:layout_width="match_parent"android:layout_height="wrap_content"android:textSize="16sp" /></RadioGroup></LinearLayout></ScrollView></LinearLayout></android.support.constraint.ConstraintLayout>
4.MainActivity.java
package com.example.yogi.networktest;import android.content.Intent;
import android.os.Handler;
import android.os.Looper;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TextView;import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;import java.io.StringReader;
import java.util.ArrayList;import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;public class MainActivity extends AppCompatActivity implements View.OnClickListener {private Button sendReq;private ArrayList<Question> questions = new ArrayList<>();private RadioGroup ques_group[] = new RadioGroup[5];private RadioButton quesRadioButton[] = new RadioButton[18];private String userAnswer[] = new String[50];private TextView ques_title[] = new TextView[5];//private int userAnsLoop = 0;//用于设置用户答案时的循环@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initView();}private void initView() {sendReq = findViewById(R.id.send_request);sendReq.setOnClickListener(this);ques_group[0] = findViewById(R.id.ques_choices1);ques_group[1] = findViewById(R.id.ques_choices2);ques_group[2] = findViewById(R.id.ques_choices3);ques_group[3] = findViewById(R.id.ques_choices4);ques_group[4] = findViewById(R.id.ques_choices5);ques_title[0] = findViewById(R.id.ques_title1);ques_title[1] = findViewById(R.id.ques_title2);ques_title[2] = findViewById(R.id.ques_title3);ques_title[3] = findViewById(R.id.ques_title4);ques_title[4] = findViewById(R.id.ques_title5);quesRadioButton[0] = findViewById(R.id.choiceA1);quesRadioButton[1] = findViewById(R.id.choiceA2);quesRadioButton[2] = findViewById(R.id.choiceA3);quesRadioButton[3] = findViewById(R.id.choiceA4);quesRadioButton[4] = findViewById(R.id.choiceA5);quesRadioButton[5] = findViewById(R.id.choiceB1);quesRadioButton[6] = findViewById(R.id.choiceB2);quesRadioButton[7] = findViewById(R.id.choiceB3);quesRadioButton[8] = findViewById(R.id.choiceB4);quesRadioButton[9] = findViewById(R.id.choiceB5);quesRadioButton[10] = findViewById(R.id.choiceC1);quesRadioButton[11] = findViewById(R.id.choiceC2);quesRadioButton[12] = findViewById(R.id.choiceC3);quesRadioButton[15] = findViewById(R.id.choiceD1);quesRadioButton[16] = findViewById(R.id.choiceD2);quesRadioButton[17] = findViewById(R.id.choiceD3);for(int i = 0;i < quesRadioButton.length;i++){if(i != 13 && i != 14)quesRadioButton[i].setOnClickListener(this);}/*for(userAnsLoop = 0;userAnsLoop < ques_group.length;userAnsLoop++){ques_group[userAnsLoop].setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {@Overridepublic void onCheckedChanged(RadioGroup group, int checkedId) {int id = group.getCheckedRadioButtonId();RadioButton radioBtn = MainActivity.this.findViewById(id);String text = radioBtn.getText().toString();userAnswer[userAnsLoop] = text.split("\\.")[0];Log.d("MainActivity", "userAnsLoop: "+userAnsLoop+"值:"+userAnswer[userAnsLoop]);}});}*/}public void onClick(View v){if(v.getId() == R.id.send_request){if(sendReq.getText().toString().equals("开始考试")){//发送http请求并解析、显示题目sendRequestWithOkHttp();sendReq.setText("提交试卷");}else if(sendReq.getText().toString().equals("提交试卷")){//获得每一题的答案for(int i = 0;i < ques_group.length;i++){//该RadioGroup下有几个RadioButonint count = ques_group[i].getChildCount();//遍历RadioButon,如果被选中则存入答案数组for(int j = 0 ;j < count;j++){RadioButton rb = (RadioButton)ques_group[i].getChildAt(j);if(rb.isChecked()){String text = rb.getText().toString();userAnswer[i] = text.split("\\.")[0];Log.d("MainActivity", "序号: "+i+" 值:"+userAnswer[i]);}}}getScoresAndSkip();}}}private void getScoresAndSkip() {int score = 0;int i = 0;for(Question ques:questions){if(ques.getAnswer().equals(userAnswer[i])){score+=20;}i++;}Intent intent = new Intent(MainActivity.this,ResultActivity.class);intent.putExtra("score",String.valueOf(score));startActivity(intent);}//有许多出色的网络通信库都可以替代原生的HttpURLConnection,其中OkHttp是比较出色的一个private void sendRequestWithOkHttp() {//开启线程来发起网络请求(使用get方法提交请求)/*如果是Post方法:先构建一个RequestBody对象来存放待提交的数据RequestBody requestBody = new FormBody.Builder().add("username", "admin").add("password", "123456").builder();然后在Request.Builder构造器调用post()方法将RequestBody对象传入Request request = new Request.Builder().url("http://www.baidu.com").post(requestBody).build();其他相同*/new Thread(new Runnable () {@Overridepublic void run() {try {//创建OkHttpClient实例OkHttpClient client = new OkHttpClient();//创建Request对象Request request = new Request.Builder()//.url("http://localhost:8080/AndroidOnlineExamQues/question.xml") //通过url()方法设定目标的网络地址.url("http://10.0.2.2:8080/AndroidOnlineExamQues/question.xml")//注意这里不能像上面一样用localhost,因为虚拟机会以为是自己的localhost而不是电脑的.build();//创建一个Call对象,并调用它的execute()方法来发送请求和接受服务器返回的数据Response response = client.newCall(request).execute();//使用Response对象接受服务器返回的数据 然后使用response.body().string()方法获得具体的内容String responseData = response.body().string();parseXMLWithPull(responseData);} catch(Exception e) {e.printStackTrace();}// 在子线程中实例化Handler同样是可以的,只要在构造函数的参数中传入主线程的Looper即可Handler handler = new Handler(Looper.getMainLooper());// 通过Handler的post Runnable到UI线程的MessageQueue中去即可handler.post(new Runnable() {@Overridepublic void run() {// 在MessageQueue出队该Runnable时进行的操作int quesCount = 0;for(Question aQues:questions) {ques_title[quesCount].setText(aQues.getTitle());quesRadioButton[quesCount].setText(aQues.getChoiceA());quesRadioButton[quesCount + 5].setText(aQues.getChoiceB());if(!aQues.getChoiceC().equals("")){quesRadioButton[quesCount + 10].setText(aQues.getChoiceC());quesRadioButton[quesCount + 15].setText(aQues.getChoiceD());}ques_group[quesCount].setVisibility(View.VISIBLE);quesCount++;}}});}}).start();}private void parseXMLWithPull(String xmlData) {try {//获得一个XmlPullParserFactory实例XmlPullParserFactory factory = XmlPullParserFactory.newInstance();//得到XmlPullParser对象XmlPullParser xmlPullParser = factory.newPullParser();//调用xmlPullParser的setInput方法将服务器返回的XML数据传入开始解析xmlPullParser.setInput(new StringReader(xmlData));//获得当前的解析事件int eventType = xmlPullParser.getEventType();String title="";String choiceA="";String choiceB="";String choiceC="";String choiceD="";String ans="";String quesId="";int quesCount = 0;while (eventType != XmlPullParser.END_DOCUMENT) {//注意这个不能写在这里,不然每次都初始化为0,每道题都是1不会有2、3、4、5//int quesCount = 0;//getName()方法获得当前节点的名字String nodeName = xmlPullParser.getName();//如果发现节点名等于title等等,就调用nextText()方法来获取节点内具体的内容switch(eventType) {//开始解析节点,START_TAG和END_TAG分别表示开始标签和结束标签,例如<title>为开始标签,而</title>为结束标签case XmlPullParser.START_TAG: {if ("title".equals(nodeName)) {quesCount++;title = String.valueOf(quesCount)+"."+xmlPullParser.nextText();//aNewQues.setTitle(xmlPullParser.nextText());//Log.d("MainActivity", "title: "+xmlPullParser.nextText());} else if ("choiceA".equals(nodeName)) {choiceA = "A." + xmlPullParser.nextText();//aNewQues.setChoiceA(xmlPullParser.nextText());} else if ("choiceB".equals(nodeName)) {choiceB = "B." + xmlPullParser.nextText();//aNewQues.setChoiceB(xmlPullParser.nextText());}else if ("choiceC".equals(nodeName)) {choiceC = "C." + xmlPullParser.nextText();//aNewQues.setChoiceC(xmlPullParser.nextText());}else if ("choiceD".equals(nodeName)) {choiceD = "D." + xmlPullParser.nextText();//aNewQues.setChoiceD(xmlPullParser.nextText());}else if ("answer".equals(nodeName)) {ans = xmlPullParser.nextText();//aNewQues.setAnswer(xmlPullParser.nextText());}else if ("id".equals(nodeName)) {quesId = xmlPullParser.nextText();//aNewQues.setId(xmlPullParser.nextText());}break;}//完成解析某道题目,就把题目放到list里case XmlPullParser.END_TAG: {if("question".equals(nodeName)) {Question aNewQues = new Question(quesId,title,ans,choiceA,choiceB,choiceC,choiceD);choiceC = "";choiceD = "";questions.add(aNewQues);}break;}default:break;}eventType = xmlPullParser.next();}} catch(Exception e) {e.printStackTrace();}}}
5.AndroidManifect.xml——加入网络权限的申请
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.example.yogi.networktest">……<uses-permission android:name="android.permission.INTERNET" />
</manifest>
注意我们接下来要建新的活动,如果是右键新建Activity,那么会自动帮我们在这里注册,如果新建的是java则需要自己注册一下。
6.新的Activity—ResultActivity.java
package com.example.yogi.networktest;import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;public class ResultActivity extends AppCompatActivity implements View.OnClickListener{TextView score,isPass;Button retest;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_result);score = findViewById(R.id.score);isPass = findViewById(R.id.isPass);Intent intent = getIntent();String s = intent.getStringExtra("score");if(s != null){score.setText("您的分数为:"+s);int sc = Integer.valueOf(s);if(sc < 80){isPass.setText("不及格,您可以点击下方按钮重新考试。");retest = findViewById(R.id.retest);retest.setOnClickListener(this);retest.setVisibility(View.VISIBLE);}else{isPass.setText("恭喜,通过考试。");}}}@Overridepublic void onClick(View v){Intent intent = new Intent(ResultActivity.this,MainActivity.class);startActivity(intent);}
}
7.activity_result.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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"tools:context=".ResultActivity"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"><TextViewandroid:id="@+id/score"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textSize="30dp"android:layout_marginTop="20dp"/><TextViewandroid:id="@+id/isPass"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textSize="21dp"android:layout_marginVertical="10dp"/><Buttonandroid:id="@+id/retest"android:layout_width="match_parent"android:layout_height="wrap_content"android:visibility="invisible"android:text="重新考试"/></LinearLayout></android.support.constraint.ConstraintLayout>
安卓使用网络技术实战——简易的在线考试app相关推荐
- 计算机网络技术与应用多选题与答案,南开20秋学期(1709、1803、1809、1903、1909、2003、2009 )《网络技术与应用》在线作业【答案】...
南开20秋学期(1709.1803.1809.1903.1909.2003.2009 )<网络技术与应用>在线作业 共50道题 总分:100分 100分 单选题 多选题 判断题 一.单选题 ...
- 下列哪项不属于以太网交换机的特点_南开19秋学期(1709、1803、1809、1903、1909) 《网络技术与应用》在线作业题目【标准答案】...
19秋学期(1709.1803.1809.1903.1909) <网络技术与应用>在线作业-0002 试卷总分:100 得分:100 一.单选题 (共 30 道试题,共 60 分) 1. ...
- C/C++项目实战:实现在线考试系统,附源码
在线考试系统是国内市场占有率最高的通用化网络考试软件,经过数千家客户的长期实践检验,适用于需要开展网络考试测评的学校.企业.政府和军队,极大地降低客户的硬件投资成本. C++在线考试系统,Access ...
- 【免费活动】解析腾讯云音视频通信三大核心网络技术实战与创新
随着互联网的发展越来越成熟,移动终端成为我们人手必备的生活用品,云计算的普及与高速发展,4G.5G网络的瓜熟蒂落,我们真正的进入了全真互联网时代.2020年,一场突如其来的疫情,很多传统行业不得不将线 ...
- 解析腾讯云音视频通信三大核心网络技术实战与创新
随着互联网的发展越来越成熟,移动终端成为我们人手必备的生活用品,云计算的普及与高速发展,4G.5G网络的瓜熟蒂落,我们真正的进入了全真互联网时代.2020年,一场突如其来的疫情,很多传统行业不得不将线 ...
- Android的在线考试app
效果图 项目编写顺序 集成Retrofit网络请求插件 集成数据库操作Greendao插件 定时器编写 编写题目悬浮框 1.集成Retrofit网络请求插件 引用依赖并加入网络请求权限: build. ...
- 基于java的网络在线考试管理系统的设计与实现--毕业开题报告
基于java的网络在线考试管理系 统的设计与实现开题报告–毕业设计 最近grace刚完成毕业设计 通过了赶紧来给宝贝们分享我的成果哈哈 设计题目:基于java的网络在线考试管理系统的设计与实现 一.选 ...
- 基于uni-app的安卓在线考试系统软件设计
随着编程技术的进步,出现了越来越多的跨平台开发语言和框架,比较常用的有Flutter.uni-app.Ionic.React native等,在我的开发实践中感觉Flutter虽然接近原生,谷歌独创语 ...
- 自考计算机与网络技术基础知识点,《计算机与网络技术基础》课程考试说明
<计算机与网络技术基础>(0894)课程考试说明(全国统一命题考试) 一.考试标准和原则 1.考试标准 <计算机与网络技术基础>课程是电子商务专业(专科)开设的一门专业必考课程 ...
最新文章
- 微软推出 .NET 官方社区论坛
- vue 实现 js css html分离
- django html显示xml,如何将HTML与Django集成?
- java手机状态栏圆形图标,android实现状态栏添加图标的函数实例
- openwrt gstreamer实例学习笔记(四. gstreamer Bins)
- ABP框架系列之六:(Value-Objects-值对象)
- HTML:颜色列表(自用)
- 全网首发:Proguard加密后的getResource()问题
- Python3迅雷vip账号批量抓取导入excel中
- 什么是冒烟测试?什么是回归测试?
- response.addCookie(cookie);报错分析
- java 条件运算符_Java条件运算符
- 手机刷的面具是什么_小米9刷Magisk(面具)详细教程
- bak 安全牛 kali link
- 油管最火KMP算法讲解,阿三哥的源代码!
- 超大模型分布式训练DeepSpeed教程
- Github每日精选(第48期):SQLite下的知识库memos
- KVM虚拟机支持虚拟化(kvm虚拟化嵌套)
- 感悟西游记——成气候的妖精都是领导家的
- 连接共享打印报错0X0000011b