智能排隊機
- 匯入閉包與權限申明
- 匯入閉包
- 申明權限
- 網路安全問題
- 問題描述
- 解決方案
- Activity
- WelComeActvity
- 效果圖
- 描述
- 代碼
- LoginActivity
- 效果圖
- 描述
- 代碼
- MainActivity
- 效果圖
- 描述
- 代碼
- HistoricalDataActivity
- 效果圖
- 描述
- 代碼
- 后臺資料
- 總結
匯入閉包與權限申明
匯入閉包
其中包括
1.新大陸閉包:用于連接新大陸云平臺,通過底層硬體設備獲取資料,并上傳至云平臺,移動端端通過此閉包,連接云平臺,實時獲取資料
2.Google推出的MaterialDesign API
3.MPAndroidChar:繪制折線圖等
implementation project(path: ':nlecloud-sdk')
implementation 'com.google.android.material:material:1.1.0-alpha09'
implementation 'com.getbase:floatingactionbutton:1.10.1'
implementation 'com.google.android.material:material:1.0.0'
implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0'
申明權限
因為要與獲取云平臺資料,所有申明網路權限
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.VIBRATE" />
網路安全問題
問題描述
Google表示,為保證用戶資料和設備的安全,針對下一代 Android 系統(Android P) 的應用程式,將要求默認使用加密連接,這意味著 Android P 將禁止 App 使用所有未加密的連接,因此運行 Android P 系統的安卓設備無論是接識訓者發送流量,未來都不能明碼傳輸,需要使用下一代(Transport Layer Security)傳輸層安全協議,而 Android Nougat 和 Oreo 則不受影響,

解決方案
在Android Studio,res目錄下創建一個xml包,再在xml包內創建一個network_security_config.xml檔案(檔案名自定義)
res->xml->network_security_config.xml
代碼如下:
<network-security-config>
<base-config cleartextTrafficPermitted="true" />
</network-security-config>
然后在清單檔案中參考
android:networkSecurityConfig="@xml/network_security_config"
Activity
WelComeActvity
效果圖
描述
右上角按鈕數字從5開始倒計時,采用Handler異步通信實作,到0時,自動跳轉到登錄界面,代碼如下:
Handler handler = new Handler( ){
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage( msg );
if (msg.what == 0 && Flag) {
int Count = CountDown();
btn_Skip.setText( "跳過 " + Count );
handler.sendEmptyMessageDelayed( 0,1000 );
}
}
};
代碼
代碼中Flag用于Handler倒計時未結束,點擊按鈕進行跳轉,異步通信未結束,防止再次渲染
**
* Author:FranzLiszt
* Completion time:9-20*/
public class WelComeActivity extends AppCompatActivity {
private Button btn_Skip,GetInto;
private int TotalNumber = 5;
/*用于點擊跳過或者進入應用按鈕之后,界面發生跳轉,但執行緒并未停止,時間到達,仍會重新渲染一次,
使用此標志,用來控制不執行異步介紹的資訊,從此達到中斷的效果*/
private boolean Flag = true;
Handler handler = new Handler( ){
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage( msg );
if (msg.what == 0 && Flag) {
int Count = CountDown();
btn_Skip.setText( "跳過 " + Count );
handler.sendEmptyMessageDelayed( 0,1000 );
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate( savedInstanceState );
if (Build.VERSION.SDK_INT >= 21) {
View decorView = getWindow().getDecorView();
decorView.setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE );
getWindow().setStatusBarColor( Color.TRANSPARENT );
}
setContentView( R.layout.activity_wel_come );
InitView();
}
/*5s之后自動跳轉*/
private void InitView(){
btn_Skip = findViewById( R.id.btn_Skip );
GetInto = findViewById( R.id.GetInto);
handler.sendEmptyMessageDelayed( 0,1000 );
}
private int CountDown(){
if (TotalNumber -- == 1){
ReturnActivity(LoginActivity.class);
}
return TotalNumber;
}
public void Skip(View view) {
Flag = false;
ReturnActivity(LoginActivity.class);
}
public void GetIntoApp(View view) {
Flag = false;
ReturnActivity(LoginActivity.class);
}
private void ReturnActivity(Class Activity){
startActivity( new Intent( WelComeActivity.this,Activity ) );
}
}
LoginActivity
效果圖
描述
UI部分采用Google的MD組件庫,此處省略,代碼部分,主要獲取用戶輸入的賬戶、密碼傳輸給云平臺進行匹配,如果密碼正確,服務器會回傳一個AccessToken(訪問令牌)JSON資料,然后我們進行反序列化,使用此令牌進行后續操作
代碼
獲取AccessToken之后,通過SharedPreferences封裝類SP進行保存(SP封裝類在另一篇博文中有詳細解鎖,此處省略
https://editor.csdn.net/md/?articleId=120434977
public class LoginActivity extends AppCompatActivity {
private EditText mUserName,mPassWord;
private String AccessToken = "";
private SP sp;
private NetWorkBusiness business;
private Context context = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate( savedInstanceState );
if (Build.VERSION.SDK_INT >= 21) {
View decorView = getWindow().getDecorView();
decorView.setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE );
getWindow().setStatusBarColor( Color.TRANSPARENT );
}
setContentView( R.layout.activity_login );
InitView();
}
private void InitView(){
mUserName = findViewById( R.id.username );
mPassWord = findViewById( R.id.password );
if (context == null){
context = LoginActivity.this;
}
}
private void LoginMethod(){
String UserName = mUserName.getText().toString().trim();
String PassWord = mPassWord.getText().toString().trim();
if (TextUtils.isEmpty( UserName )){
Toast.makeText( context,"UserName cannot be empty",Toast.LENGTH_SHORT ).show();
return;
}
if (TextUtils.isEmpty( PassWord )){
Toast.makeText( context,"PassWord cannot be empty",Toast.LENGTH_SHORT ).show();
return;
}
business = new NetWorkBusiness( AccessToken, Param.URL );
business.signIn( new SignIn( UserName, PassWord ), new NCallBack<BaseResponseEntity<User>>(getApplicationContext()) {
@Override
protected void onResponse(BaseResponseEntity<User> response) {
}
@Override
public void onResponse(Call<BaseResponseEntity<User>> call, Response<BaseResponseEntity<User>> response) {
super.onResponse( call, response );
BaseResponseEntity<User> body = response.body();
if (body != null && body.getStatus() == 0){
sp = new SP( context );
AccessToken = body.getResultObj().getAccessToken();
/*將AccessToken存入sp*/
sp.PutData( context,"AccessToken",AccessToken );
ReturnActivity(MainActivity.class);
Toast.makeText( context,"Login Success",Toast.LENGTH_SHORT ).show();
}else {
Toast.makeText( context,"Login Fail",Toast.LENGTH_SHORT ).show();
}
}
@Override
public void onFailure(Call<BaseResponseEntity<User>> call, Throwable t) {
super.onFailure( call, t );
Toast.makeText( context,"Exception",Toast.LENGTH_SHORT ).show();
}
} );
}
/*標題欄回傳按鈕*/
public void Exit(View view){
ReturnActivity(WelComeActivity.class);
}
/*登錄按鈕*/
public void Login(View view){
LoginMethod();
}
private void ReturnActivity(Class Activity){
startActivity( new Intent( context,Activity ) );
}
}
MainActivity
效果圖
描述
頂部兩個圓形進度潭訓根據傳入的資料,發生相對應變化
樣式變化規則如下:
- 設定最多排隊20個人,超過20人會實時顯示,但不會聯動觸發樣式效果
- 10人及以下外圓弧與文字為綠色
- 11-20人外圓弧與文字為紫色
- 大于20及,外圓弧與文字為紅色
中間輸入框為語音模塊,輸入的字串,會通過云平臺傳入底層設備,底層設備會相對應語音播報相關內容
點擊取消排隊之后,所有功能置灰,不起作用,唯有排隊按鈕可以使用,反之,排隊中,其余按鈕均可使用,唯獨排隊按鈕不可使用
代碼
/**
* Author:FranzLiszt
* Function:排隊叫號
* Tips:設定最多排隊20個人,超過20人會實時顯示,但不會聯動觸發樣式效果
* 10人及以下外圓弧與文字為綠色
* 11-20人外圓弧與文字為紫色
* 大于20及,外圓弧與文字為紅色
* 硬體沒有限制,軟體限制人數*/
/**
* 核心思想:
* 取號:獲取一個號碼,開始排隊
* 叫號:當前方排隊人數小于3時,系統提示請前往現場辦理業務,無需進行排隊,所有功能置灰*/
public class MainActivity extends AppCompatActivity {
/*圓形進度條上方提示文字
* 作用:跟隨進度條外圓弧顏色的變化而變化*/
private TextView Text_CurrentPeople,Text_CurrentTime;
/*圓形進度條
* 作用:外圓弧跟隨排隊人數與剩余時間的變化而變化*/
private ProgressBarView CurrentPeople,CurrentTime;
/*需要輸入的內容*/
private EditText InputMessage;
/*按鍵*/
private Button SendMessage,ReadProgress,ReadRecord,LineUp,CancelLineUp;
private RelativeLayout TipLayout;
private TextView TipText,btn_Agree,pop_TipText,pop_TipAgree;
private SP sp;
private String AccessToken = "";
private NetWorkBusiness business;
private Context context = null;
/*用來判斷是否取消排隊,中斷執行緒*/
private boolean Flag = true;
/*用來裝載獲取服務器的排隊人數*/
private int mCurrentNumber;
/*用來裝載獲取服務器的等候時間
* 時間 = 人數 * 5
* 基數自定義*/
private int mCurrentWaitTime;
/*用來判斷是否正在排隊,如果正在排隊,排隊按鈕無法點擊*/
private boolean EnableFlag = false;
private Thread thread;
private boolean DialogFlag = true;
private PopupWindow mPopupWindow,mPopupWindow_2;
private View TipView,TipView_2;
private static final int COMPLETE = 2;
private static final int START = 1;
private static final int STOP = 0;
Handler handler = new Handler( ){
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage( msg );
switch (msg.what){
case COMPLETE:
CompleteQueuing();
break;
case START:
GetAndSet();
break;
case STOP:
clearStyle();
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate( savedInstanceState );
if (Build.VERSION.SDK_INT >= 21) {
View decorView = getWindow().getDecorView();
decorView.setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE );
getWindow().setStatusBarColor( Color.TRANSPARENT );
}
setContentView( R.layout.activity_main );
InitView();
GetSpValue();
Listener();
GetCurrentPeople();
InitPopWidows();
}
/**
* Name:InitView
* Function:初始化控制元件*/
private void InitView(){
Text_CurrentPeople = findViewById( R.id.Text_CurrentPeople );
Text_CurrentTime = findViewById( R.id.Text_CurrentTime );
InputMessage = findViewById( R.id.InputMessage );
SendMessage = findViewById( R.id.SendMessage );
ReadProgress = findViewById( R.id.ReadProgress );
ReadRecord = findViewById( R.id.ReadRecord );
LineUp = findViewById( R.id.btn_LineUp );
CancelLineUp = findViewById( R.id.btn_CancelLineUp );
CurrentPeople = findViewById( R.id.CurrentPeople );
CurrentTime = findViewById( R.id.CurrentTime );
TipLayout = findViewById( R.id.TipLayout );
TipText = findViewById( R.id.TipText );
if (context == null){
context = MainActivity.this;
}
LineUp.setBackgroundResource( R.drawable.btn_notenable );
LineUp.setEnabled( false );
}
/**
* Name:GetSpValue
* Function:獲取AccessToken
* 實體化NetWorkBusiness物件*/
private void GetSpValue(){
sp = new SP( context );
AccessToken = (String) sp.GetData( context,"AccessToken","" );
business = new NetWorkBusiness( AccessToken, Param.URL );
}
private void GetCurrentPeople(){
thread = new Thread( ){
@Override
public void run() {
super.run();
while (true) {
while (Flag) {
try {
Thread.sleep( 3000 );
} catch (InterruptedException e) {
e.printStackTrace();
}
Message message = new Message();
message.what = START;
handler.sendMessage( message );
}
}
}
};
thread.start();
}
private void GetAndSet(){
business.getSensors( Param.DEVICEID, Param.QUEUENUMBER, new NCallBack<BaseResponseEntity<List<SensorInfo>>>(context) {
@Override
protected void onResponse(BaseResponseEntity<List<SensorInfo>> response) {
}
@Override
public void onResponse(Call<BaseResponseEntity<List<SensorInfo>>> call, Response<BaseResponseEntity<List<SensorInfo>>> response) {
super.onResponse( call, response );
BaseResponseEntity<List<SensorInfo>> body = response.body();
if (body!=null && body.getStatus() == 0){
mCurrentNumber = Integer.parseInt( body.getResultObj().get( 0 ).getValue() );
mCurrentWaitTime = mCurrentNumber * 5;
sp.PutData( context,"CurrentNumber",mCurrentNumber );
sp.PutData( context,"CurrentWaitTime",mCurrentWaitTime );
}
}
} );
runOnUiThread( ()->{
if (mCurrentNumber >= 20){
/*人數大于20,紅色*/
setRed();
DialogFlag = true;
DisplayLayout_Queuing();
}else if (mCurrentNumber < 20 && mCurrentNumber > 10 ){
/*人數10-20,紫色*/
setViolet();
DialogFlag = true;
DisplayLayout_Queuing();
}else if (mCurrentNumber <= 10 && mCurrentNumber > 3){
/*人數小于10,綠色*/
setGreen();
DialogFlag = true;
DisplayLayout_Queuing();
}else if (mCurrentNumber <=3 && mCurrentNumber > 0){
if (DialogFlag){
Flag = false;
Message message = new Message();
message.what = COMPLETE;
handler.sendMessage( message );
}
}
} );
}
private void Control(String DeviceID,String Tag,Object value){
business.control( DeviceID, Tag, value, new NCallBack<BaseResponseEntity>(getApplicationContext()) {
@Override
protected void onResponse(BaseResponseEntity response) {
}
@Override
public void onResponse(Call<BaseResponseEntity> call, Response<BaseResponseEntity> response) {
super.onResponse( call, response );
BaseResponseEntity<User> body = response.body();
if (body == null && body.getStatus() != 0){
Toast.makeText( context,"請求失敗",Toast.LENGTH_SHORT ).show();
}
}
@Override
public void onFailure(Call<BaseResponseEntity> call, Throwable t) {
super.onFailure( call, t );
Toast.makeText( context,"例外",Toast.LENGTH_SHORT ).show();
}
} );
}
private void SendVoiceMessage(){
String Message = InputMessage.getText().toString().trim();
Control( Param.DEVICEID,Param.VOIVE,Message );
}
private void InitPopWidows(){
TipView = LayoutInflater.from( context ).inflate( R.layout.pop_item,null );
btn_Agree = TipView.findViewById( R.id.btn_Agree );
mPopupWindow = new PopupWindow( TipView, ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT );
mPopupWindow.setFocusable( true ); //獲取焦點
mPopupWindow.setBackgroundDrawable( new BitmapDrawable() );
mPopupWindow.setOutsideTouchable( true ); //點擊外面地方,取消
mPopupWindow.setTouchable( true ); //允許點擊
mPopupWindow.setAnimationStyle( R.style.PopupWindow ); //設定影片
btn_Agree.setOnClickListener( new View.OnClickListener() {
@Override
public void onClick(View v) {
//EnableFlag = true;
setGrey();
setStyleInvalid();
setButtonNotEnabled();
/*手機震動*/
Vibrator vibrator = (Vibrator) getSystemService( Service.VIBRATOR_SERVICE);
vibrator.vibrate(100);
mPopupWindow.dismiss();
}
} );
TipView_2 = LayoutInflater.from( context ).inflate( R.layout.tip_pop_item,null );
pop_TipText = TipView_2.findViewById( R.id.pop_TipsText );
pop_TipAgree = TipView_2.findViewById( R.id.pop_TipAgree );
mPopupWindow_2 = new PopupWindow( TipView_2, ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT );
mPopupWindow_2.setFocusable( true ); //獲取焦點
mPopupWindow_2.setBackgroundDrawable( new BitmapDrawable() );
mPopupWindow_2.setOutsideTouchable( true ); //點擊外面地方,取消
mPopupWindow_2.setTouchable( true ); //允許點擊
mPopupWindow_2.setAnimationStyle( R.style.PopupWindow ); //設定影片
pop_TipAgree.setOnClickListener( new View.OnClickListener() {
@Override
public void onClick(View v) {
mPopupWindow_2.dismiss();
}
} );
}
private void DisPlayPopWindows(){
mPopupWindow.showAtLocation( TipView, Gravity.CENTER,0,0 );
}
private void ShowPopWindows(){
pop_TipText.setText( "目前前方剩余"+mCurrentNumber+"人,需要等候"+mCurrentWaitTime+"min" );
mPopupWindow_2.showAtLocation( TipView_2,Gravity.CENTER,0,0 );
}
private void DisplayLayout_Queuing(){
TipLayout.setVisibility( View.VISIBLE );
TipText.setText( "當前正在排隊中,請文明排隊" );
}
private void DisplayLayout_CancelQueuing(){
TipLayout.setVisibility( View.VISIBLE );
TipText.setText( "當前號碼已作廢,請重新排隊" );
}
private void DisplayLayout_CallNumber(){
TipLayout.setVisibility( View.VISIBLE );
TipText.setText( "排隊完成,請前往現場辦理業務" );
}
private void CompleteQueuing(){
/*人數小于3,給予提示*/
DisplayLayout_CallNumber();
DisPlayPopWindows();
}
private void setRed(){
Text_CurrentPeople.setTextColor( getResources().getColor( R.color.colorRed ) );
Text_CurrentTime.setTextColor( getResources().getColor( R.color.colorRed ) );
Text_CurrentPeople.setText( mCurrentNumber+getResources().getString( R.string.Tips_2 ) );
Text_CurrentTime.setText( mCurrentWaitTime+"Min" );
CurrentPeople.setProgress( 100 );
CurrentPeople.setCircleColor( getResources().getColor( R.color.colorRed ) );
CurrentPeople.setContent( "擁擠" );
CurrentTime.setProgress( 100 );
CurrentTime.setCircleColor( getResources().getColor( R.color.colorRed ) );
CurrentTime.setContent( "時間長" );
}
private void setViolet(){
Text_CurrentPeople.setTextColor( getResources().getColor( R.color.colorViolet ) );
Text_CurrentTime.setTextColor( getResources().getColor( R.color.colorViolet ) );
Text_CurrentPeople.setText( mCurrentNumber+getResources().getString( R.string.Tips_2 ) );
Text_CurrentTime.setText( mCurrentWaitTime+"Min" );
CurrentPeople.setProgress( mCurrentWaitTime );
CurrentPeople.setCircleColor( getResources().getColor( R.color.colorViolet ) );
CurrentPeople.setContent( "正常" );
CurrentTime.setProgress( mCurrentWaitTime );
CurrentTime.setCircleColor( getResources().getColor( R.color.colorViolet ) );
CurrentTime.setContent( "時間中" );
}
private void setGreen(){
Text_CurrentPeople.setTextColor( getResources().getColor( R.color.colorGreen ) );
Text_CurrentTime.setTextColor( getResources().getColor( R.color.colorGreen ) );
Text_CurrentPeople.setText( mCurrentNumber+getResources().getString( R.string.Tips_2 ) );
Text_CurrentTime.setText( mCurrentWaitTime+"Min" );
CurrentPeople.setProgress( mCurrentWaitTime );
CurrentPeople.setCircleColor( getResources().getColor( R.color.colorGreen ) );
CurrentPeople.setContent( "暢通" );
CurrentTime.setProgress( mCurrentWaitTime );
CurrentTime.setCircleColor( getResources().getColor( R.color.colorGreen ) );
CurrentTime.setContent( "時間短" );
}
private void setGrey(){
Text_CurrentPeople.setTextColor( getResources().getColor( R.color.colorGrey ) );
Text_CurrentTime.setTextColor( getResources().getColor( R.color.colorGrey ) );
Text_CurrentPeople.setText( "0"+getResources().getString( R.string.Tips_2 ) );
Text_CurrentTime.setText( "0 Min" );
CurrentPeople.setProgress( 0 );
CurrentPeople.setCircleColor( getResources().getColor( R.color.colorGrey ) );
CurrentPeople.setContent( "無" );
CurrentTime.setProgress( 0 );
CurrentTime.setCircleColor( getResources().getColor( R.color.colorGrey ) );
CurrentTime.setContent( "無" );
}
/*按鈕不能點擊*/
private void setButtonNotEnabled(){
SendMessage.setEnabled( false );
ReadProgress.setEnabled( false );
ReadRecord.setEnabled( false );
CancelLineUp.setEnabled( false );
InputMessage.setEnabled( false );
LineUp.setEnabled( true );
InputMessage.setText( "" );
}
/*樣式灰色*/
private void setStyleInvalid(){
SendMessage.setBackgroundResource( R.drawable.btn_notenable );
ReadProgress.setBackgroundResource( R.drawable.btn_notenable );
ReadRecord.setBackgroundResource( R.drawable.btn_notenable );
CancelLineUp.setBackgroundResource( R.drawable.btn_notenable );
LineUp.setBackgroundResource( R.drawable.btn_login );
}
/*樣式恢復正常*/
private void setNormalStyle(){
SendMessage.setBackgroundResource( R.drawable.btn_login );
ReadProgress.setBackgroundResource( R.drawable.btn_login );
ReadRecord.setBackgroundResource( R.drawable.btn_login );
CancelLineUp.setBackgroundResource( R.drawable.btn_login );
LineUp.setBackgroundResource( R.drawable.btn_notenable );
}
/*按鈕允許點擊*/
private void setButtonEnabled(){
SendMessage.setEnabled( true );
ReadProgress.setEnabled( true );
ReadRecord.setEnabled( true );
CancelLineUp.setEnabled( true );
InputMessage.setEnabled( true );
LineUp.setEnabled( false );
}
private void NormalStyle(){
DialogFlag = false;
Flag = true;
setNormalStyle();
setButtonEnabled();
Message message = new Message();
message.what = START;
handler.sendMessage( message );
}
/*排隊取消狀態
* 所有控制元件置灰*/
private void clearStyle(){
Flag = false;
DisplayLayout_CancelQueuing();
setGrey();
setButtonNotEnabled();
setStyleInvalid();
}
private void StopThread(){
Flag = false;
try {
thread.join( 1000 );
} catch (InterruptedException e) {
e.printStackTrace();
}
Message message = new Message();
message.what = STOP;
handler.sendMessage( message );
}
/*回傳按鈕*/
public void Exit(View view){
ReturnActivity( LoginActivity.class );
}
private void ReturnActivity(Class Activity){
startActivity( new Intent( context,Activity ) );
}
private void Listener(){
OnClick onClick = new OnClick();
SendMessage.setOnClickListener( onClick );
ReadRecord.setOnClickListener( onClick );
ReadProgress.setOnClickListener( onClick );
LineUp.setOnClickListener( onClick );
CancelLineUp.setOnClickListener( onClick );
}
class OnClick implements View.OnClickListener{
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.SendMessage:
SendVoiceMessage();
break;
case R.id.btn_LineUp:
NormalStyle();
break;
case R.id.btn_CancelLineUp:
StopThread();
break;
case R.id.ReadProgress:
ShowPopWindows();
break;
case R.id.ReadRecord:
ReturnActivity( HistoricalDataActivity.class );
break;
}
}
}
}
HistoricalDataActivity
效果圖
描述
通過在子執行緒實時獲取資料,然后通過runOnUiThread跳轉到主執行緒,實時更新UI,具體使用此處省略,代碼基本每句都有注釋
代碼
public class HistoricalDataActivity extends AppCompatActivity {
private LineChart LineChart;
private String[] mDate;
private LineData mLineData; // 線集合,所有折線以陣列的形式存到此集合中
private LineDataSet mDataSet; // 點集合,即一條折線
private List<Entry> mEntries; // Entry為某條折線上的一個點,其List封裝于LineDataSet中
private Timer mTimer; // 定時器,動態獲取資料
private NetWorkBusiness mNetWorkBusiness;
private String mAccessToken;
private SP sp;
private Context context = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate( savedInstanceState );
if (Build.VERSION.SDK_INT >= 21) {
View decorView = getWindow().getDecorView();
decorView.setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE );
getWindow().setStatusBarColor( Color.TRANSPARENT );
}
setContentView( R.layout.activity_historical_data );
InitView();
InitLineChart();
}
private void InitView(){
LineChart = findViewById( R.id.LineChart );
if (context == null){
context = HistoricalDataActivity.this;
}
sp = new SP( context );
mAccessToken = (String) sp.GetData( context,"AccessToken","" );
mNetWorkBusiness = new NetWorkBusiness( mAccessToken, Param.URL );
}
public void Exit(View view){
startActivity( new Intent( context,MainActivity.class ) );
}
private void InitLineChart(){
LineChart.getDescription().setText("時間");//設定圖表的描述文字,會顯示在圖表的右下角,
LineChart.getLegend().setEnabled(false);
LineChart.setTouchEnabled(true);//啟用/禁用與圖表的所有可能的觸摸互動,
LineChart.setDragEnabled(true);//啟用/禁用拖動(平移)圖表,
LineChart.setScaleEnabled(true);//啟用/禁用縮放圖表上的兩個軸,
LineChart.setDrawGridBackground(true);//如果啟用,chart繪圖區后面的背景矩形將繪制,
LineChart.setPinchZoom(false);//如果設定為true,沒縮放功能,如果false,x軸和y軸可分別放大,
LineChart.setBackgroundColor(getResources().getColor( R.color.colorWhite ));//設定背景顏色,將覆寫整個圖表視圖,此外,背景顏色可以在布局檔案.xml中進行設定,
LineChart.setBorderColor( getResources().getColor( R.color.colorBlue_1 ) );//設定chart邊框線的顏色
LineChart.setBorderWidth( 1 );//setBorderWidth(float width):設定chart邊界線的寬度,單位dp,
LineChart.getAxisRight().setEnabled(false);// 禁止繪制右坐標軸
/*X軸資料*/
XAxis xAxis = LineChart.getXAxis();
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
xAxis.setDrawGridLines(false);//設定為true,則繪制網格線,
xAxis.setLabelCount(5,false); // force:false,僅建議刻度線標簽的數量為10
xAxis.setTextSize(5);
xAxis.setGridColor( getResources().getColor( R.color.colorViolet) );
xAxis.setValueFormatter( new ValueFormatter() {
@Override
public String getFormattedValue(float value) {
return mDate[(int) value];
}
} );
/*Y軸資料*/
YAxis yAxis = LineChart.getAxisLeft();
yAxis.setAxisMinimum(0f); // 設定y軸的坐標最小值為0(人數不小于0)
yAxis.setGranularity(1f); // 設定y軸的坐標之間的最小間隔為1(單位:人)
yAxis.setLabelCount(10, false); // force:false,僅建議刻度線標簽的數量為12
yAxis.setGridColor(getResources().getColor( R.color.colorViolet));
mEntries = new ArrayList<Entry>();
mDataSet = new LineDataSet(mEntries, "排隊人數");
mDataSet.setDrawCircles(true); // 禁止繪制折線圓點
mDataSet.setHighlightEnabled(true); // 禁止高亮選中點
mDataSet.setColor(getResources().getColor( R.color.colorBlue_1)); // 折線顏色
mDataSet.setValueFormatter(new ValueFormatter() {
@Override
public String getFormattedValue(float value) {
return "";
}
});
mLineData = new LineData(mDataSet);
LineChart.setData(mLineData);
LineChart.invalidate(); // 更新視圖
mTimer = new Timer( );
mTimer.schedule( new TimerTask() {
@Override
public void run() {
mNetWorkBusiness.getSensorData( Param.DEVICEID, Param.QUEUENUMBER, "1", "1", null, null, "ASC", "10", "1", new NCallBack<BaseResponseEntity<SensorDataPageDTO>>(context) {
@Override
protected void onResponse(BaseResponseEntity<SensorDataPageDTO> response) {
}
@Override
public void onResponse(Call<BaseResponseEntity<SensorDataPageDTO>> call, Response<BaseResponseEntity<SensorDataPageDTO>> response) {
super.onResponse( call, response );
List<SensorDataPageDTO.DataPoint> body = response.body().getResultObj().DataPoints;
if (body == null){
return;
}else {
List<SensorDataPageDTO.VR> list = body.get(0).PointDTO;
SensorDataPageDTO.VR[] array = new SensorDataPageDTO.VR[list.size()];
list.toArray(array);
mDataSet.clear();
mDate = new String[array.length];
// = 0;
for (int idx = 0; idx < array.length; idx++) {
mDate[idx] = array[idx].RecordTime;
mDataSet.addEntry(new Entry((float) idx, Float.parseFloat(array[idx].Value)));
}
runOnUiThread( ()->{
// 通知LinData資料已發生變更,以重新計算繪制引數
LineChart.getLineData().notifyDataChanged();
// 讓ChartLine知道其基礎資料已更改,并執行所有必要的計算,每次動態更改資料時,若不呼叫此方法可能導致崩潰或意外行為,
LineChart.notifyDataSetChanged();
LineChart.invalidate();
} );
}
}
} );
}
},100,2000 );
}
@Override
protected void onDestroy() {
super.onDestroy();
mTimer.cancel();
}
}
后臺資料



總結
路漫漫其修遠兮,吾將上下而求索
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/302531.html
標籤:其他
上一篇:分析服務助力產品運營
