【助手APP】簡介及架構

來源:互聯網
上載者:User

標籤:android   private   新浪微博   伺服器   public   

最近沒有怎麼編碼,就把斷斷續續做了半年的畢業設計拿出來回顧一下。

校園助手,分為伺服器端與Android用戶端,在此主要介紹用戶端,伺服器是一位大神用node.js寫的。

主要實現的功能有:登陸,資訊查詢,地圖,訂餐,網頁的調用與解析,主要費勁的就是介面。


用戶端的架構是參照網上講解新浪微部落格戶端的視頻。在現在的工作中經常遇到介面更新的不便,但是這個架構就很解決了這個問題,只是剛入門的我還不知道,遇到很多挫折之後才發現這個架構的便捷。下面就開始簡單描述一下:

public class MainService extends Service implements Runnable {private static final String TAG = "MainService";private static Queue<Task> tasks = new LinkedList<Task>();private static ArrayList<Activity> appActivities = new ArrayList<Activity>();/** * 標誌執行任務的線程是否啟動 */public static boolean isRun;/** * 系統當前的使用者 */public static UserInfo nowUser;/** * 標誌當前網路是否可用 */public static boolean isNetAvailable = false;@Overridepublic void onCreate() {//啟動線程執行任務Thread thread = new Thread(this);thread.start();isRun = true;//啟動一個新線程擷取網路狀態new Thread(new Runnable() {@Overridepublic void run() {//一直擷取網路狀態isNetAvailable = NetService.getNetWorkState(MainService.this);}}).start();super.onCreate();}@Overridepublic IBinder onBind(Intent intent) {return null;}/** * 添加一個Activity對象 在每個Activity啟動的時候就調用這個函數,將自己的引用加入到主服務,便於管理,更方便介面的更新 * @param activity */public static void addActivity(Activity activity) {if (!appActivities.isEmpty()) {for (Activity at : appActivities) {if (at.getClass().getName().equals(activity.getClass().getName())) {appActivities.remove(at);break;}}}appActivities.add(activity);}/** * 根據Activity 的Name 擷取Activity對象 需要介面的引用時,就從列表擷取,很方便地得到介面的引用,從而更新介面 * @param name * @return */private static Activity getActivityByName(String name) {if (!appActivities.isEmpty()) {for (Activity activity : appActivities) {if (null != activity) {if (activity.getClass().getName().indexOf(name) > 0) {return activity;}}}}return null;}/** * 建立任務 介面需要執行耗時操作時,就調用此函數,將任務交給service執行,當執行完後就調用activity的引用來更新介面 * @param t */public static void newTask(Task t) {tasks.add(t);}/** * 主服務啟動後,一直從任務隊列中取出任務執行 */public void run() {while (isRun) {Task task = null;if (!tasks.isEmpty()) {task = tasks.poll();// 執行完任務後把改任務從任務隊列中移除if (null != task) {doTask(task);}}}}// 處理任務private void doTask(Task t) {Message msg = handler.obtainMessage();msg.what = t.getTaskId();switch (t.getTaskId()) {                                //直接在這裡進行耗時的操作                //最好將各模組進行封裝,從而使主服務的代碼簡潔明了case Task.USER_LOGIN: {UserInfo loginUser = (UserInfo) t.getTaskParams().get("loginUser");if (null != loginUser) {nowUser = LoginService.login(loginUser);//耗時操作msg.obj = nowUser;Log.i(TAG, "使用者登入————————>" + nowUser.getUserName());}break;}default:break;}// end of switchhandler.sendMessage(msg);}/** * 非同步處理訊息 */@SuppressLint("HandlerLeak")public static Handler handler = new Handler() {public void handleMessage(android.os.Message msg) {IAssistantActivity activity = null;switch (msg.what) {//處理耗時操作後,發送過來的訊息//將結果通過參數傳過來,然後通過activity的引用傳入介面case Task.USER_LOGIN: {if (null != msg.obj) {activity = (IAssistantActivity) getActivityByName("LoginActivity");}break;}default:break;}//end of switch//通過activity的引用調用相應介面的更新函數activity.refresh(msg.obj);};};/** * 退出系統 退出系統時,很方便地清楚掉所有的activity * @param context */public static void appExit(Context context) {// Finish 所有的Activityfor (Activity activity : appActivities) {if (!activity.isFinishing())activity.finish();}// 結束 ServiceIntent service = new Intent("cn.edu.wit.services.MainService");context.stopService(service);}}

這個主服務基本可以完全複用,根據需求添加一些內容即可。

再來看看介面這邊是如何搭建的

public class LoginActivity extends Activity implements IAssistantActivity {public static final String TAG = "LoginActivity";private ProgressDialog progressDialog = null;private Button btn_Login;private ClearEditText etUserId;private ClearEditText etPassword;private CheckBox cbIsRemember;private CheckBox cbIsAuto;private ImageButton ib_spinner;protected View listView;private PopupWindow pop;private List<String> userIDs ;private List<UserInfo> loginedUsers ;private MyAdapter adapter;private Animation shake ;private UserInfoServices userInfoServices = null;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.login);//初始化介面init();}@Overridepublic void init() {                //確保主服務已啟動if(!MainService.isRun){Intent service = new Intent(this, MainService.class);startService(service);}//擷取所有使用者,添加到登陸框的下拉式清單中userInfoServices = new UserInfoServices(LoginActivity.this);//擷取所用使用者initData();initView();// 把自己添加到Activity集合裡面MainService.addActivity(this);}/** * 初始化介面 */private void initView() {                //一個抖動動畫shake = AnimationUtils.loadAnimation(LoginActivity.this, R.anim.shake);etUserId = (ClearEditText) findViewById(R.id.userid);etPassword = (ClearEditText) findViewById(R.id.password);cbIsRemember = (CheckBox) findViewById(R.id.isremember);cbIsAuto = (CheckBox) findViewById(R.id.isAuto);TextView tvGetPassword = (TextView) findViewById(R.id.tvGetPassword);//"找回密碼"底線,為文字添加底線tvGetPassword.getPaint().setFlags(Paint.UNDERLINE_TEXT_FLAG);tvGetPassword.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View arg0) {Intent intent = new Intent(LoginActivity.this, FindPwdActivity.class);startActivity(intent);overridePendingTransition(SwitchActivityAnim.rightIn(), SwitchActivityAnim.rightOut());}});//登入按鈕btn_Login = (Button) findViewById(R.id.login_ok);btn_Login.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {String userId = etUserId.getText().toString().trim();String password = etPassword.getText().toString().trim();if (!"".equals(userId) && !"".equals(password)) {Log.i(TAG, "click login");UserInfo loginUser = new UserInfo();loginUser = new UserInfo();loginUser.setUserId(userId);loginUser.setPassword(password);// 調用函數建立新任務newTask(loginUser);} else {if ("".equals(userId)) {//輸入框為空白時就抖動etUserId.startAnimation(shake);etUserId.setHint("學號不可為空");etUserId.setHintTextColor(Color.RED);} else {etPassword.startAnimation(shake);etPassword.setHint("密碼不可為空");etPassword.setHintTextColor(Color.RED);}}}});//下拉式清單顯示已登入過的使用者ib_spinner = (ImageButton) findViewById(R.id.ib_spinner);ib_spinner.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {// 彈出下拉式清單ListView listView = new ListView(getApplicationContext());listView.setCacheColorHint(0x00000000);// 滑動時 不變色listView.setVerticalScrollBarEnabled(false);listView.setBackgroundColor(getResources().getColor(R.color.white));//設定透明度listView.getBackground().setAlpha(230);listView.setAdapter(new MyAdapter());pop = new PopupWindow(listView, etUserId.getWidth()+ib_spinner.getWidth(),LayoutParams.WRAP_CONTENT, true);// pop隱藏pop.setBackgroundDrawable(new ColorDrawable(0x00000000));pop.setOutsideTouchable(true);pop.setFocusable(true);//pop.setAnimationStyle(R.style.PopupAnimation);pop.showAsDropDown(etUserId, 0, -8);pop.update();}});}                //將耗時的操作封裝後交給主服務private void newTask(UserInfo loginUser) {if(!MainService.isNetAvailable){Toast.makeText(LoginActivity.this, "網路不可用!", Toast.LENGTH_LONG).show();}else {Map<String, Object> taskParams = new HashMap<String, Object>();taskParams.put("loginUser", loginUser);Task task = new Task(Task.USER_LOGIN, taskParams);//將任務加入主服務線程MainService.newTask(task);showDialg();}}/**主服務處理完任務後,通過引用來調用此函數來達到更新介面的目的 * 更新登入介面,或登入成功後跳轉,或顯示錯誤資訊 */@Overridepublic void refresh(Object... obj) {progressDialog.dismiss();if (null != obj[0]) {if (obj[0] instanceof Exception) {Exception exception = (Exception) obj[0];System.out.println(exception.getMessage());Toast.makeText(this, "登入失敗!", Toast.LENGTH_SHORT).show();return;}UserInfo user = (UserInfo)obj[0];if (null == user.getUserName() || "".equals(user.getUserName())) {//使用者名稱密碼錯誤Toast.makeText(this, "登入失敗!", Toast.LENGTH_SHORT).show();Toast.makeText(this, "請核查使用者名稱密碼以及網路連接是否可用", Toast.LENGTH_LONG).show();}else {//登入成功,跳轉到主介面Toast.makeText(LoginActivity.this, "登入成功!", Toast.LENGTH_SHORT).show();Toast.makeText(LoginActivity.this, "歡迎 "+user.getUserName()+"童鞋", Toast.LENGTH_SHORT).show();int isRemember = cbIsRemember.isChecked() ? 1 :0 ;int isAuto = cbIsAuto.isChecked() ? 1 :0 ;// 跳轉Intent intent = new Intent(LoginActivity.this, HomeActivity.class);startActivity(intent);overridePendingTransition(SwitchActivityAnim.fadeIn(), SwitchActivityAnim.bloomOut());if (1 == isAuto) {//自動登入則存入資料庫,且寫到設定檔SharedPreferencesUtil.saveLoginUser(LoginActivity.this, user);userInfoServices.insertUserInfo(user);}else if (1 == isRemember) {//記住密碼就寫入資料庫userInfoServices.insertUserInfo(user);}this.finish();}}else {Toast.makeText(LoginActivity.this, "登入失敗", Toast.LENGTH_LONG).show();}}private void initData(){userIDs = new ArrayList<String>();loginedUsers = userInfoServices.getAllLoginedUser();String users = "";if (null != loginedUsers && loginedUsers.size() > 0) {for (UserInfo user : loginedUsers) {userIDs.add(user.getUserId());users += user.getUserId()+"\t  密碼:"+user.getPassword()+"\n";}System.out.println(users);}}//將已登入的使用者列表適配到下拉式清單class MyAdapter extends BaseAdapter {@Overridepublic int getCount() {return userIDs.size();}@Overridepublic Object getItem(int position) {return userIDs.get(position);}@Overridepublic long getItemId(int position) {return position;}@Overridepublic View getView(final int position, View convertView,ViewGroup parent) {LayoutInflater inflater = LayoutInflater.from(getApplicationContext());View view = inflater.inflate(R.layout.item_userids, parent, false);TextView tv_name = (TextView) view.findViewById(R.id.tv_name);ImageButton delete = (ImageButton) view.findViewById(R.id.delete);tv_name.setText(userIDs.get(position));tv_name.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {etUserId.setText(userIDs.get(position));etPassword.setText(loginedUsers.get(position).getPassword());pop.dismiss();}});delete.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {userIDs.remove(position);adapter.notifyDataSetChanged();}});return view;}}private void showDialg() {if (null == progressDialog  ) {progressDialog = new ProgressDialog(this);}progressDialog.setMessage("正在擷取資訊...");progressDialog.show();}}

通過注釋應該能夠看清楚。


我是通過這個項目來學Android的,所以這裡面沒有太多的Android處理技巧,由於工作的原因,只是用以前的代碼,並沒有最佳化。當讓這樣也能讓自己看到慢慢成長的過程。

本文出自 “年少的風” 部落格,謝絕轉載!

【助手APP】簡介及架構

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.