Android 設計-2
架構的產生
我們先來看看 AndroidManifest.xml 這個檔案。
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.motor.sentinel"> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.READ_LOGS" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> </application> </manifest>
Avtivity 與 Fragment
只有一個主要的 Activity, 是的, 就只有一個。這不是我們要學習的, 記得, 程式語言( computer language)及 編輯器(IDE or compiler procedure)的只是一些輔助你方便使用的工具。要寫好程式主要還是在 團隊合作及架構分析 的好壞。 你很會講英文不代表你很會賣產品給講英文的外國人, 口語上有點不順暢, 你應該看得懂啦。
回去看上一篇, 整個目錄架構, 大部分的程式名稱不是 Fragment, 也不是 Activity, 也就是說盡量排除包裝在 Activity 及 Fragment 之下, 只有 Java。這樣做是希望將來還有機會不被 Activity 及Fragment 統治的機會。 阿貝發現, 很多人寫 Android 程式都會繼承 Activity, 就為了便宜行事, OO 的繼承性的確有它方便使用之處, 因為 API 包裝的太漂亮了, 所以也不擔心" 撞衫" 的問題。 嗯, 所以程式就越來越大, Android 就會越跑越慢, 不要忘了, Java Thread 不是無限量供應。
回到原點, 我的 Blog 不是初學者看的, 請不要問我 機車怎麼修, 汽車底盤怎麼頂, Java 怎麼寫, 也不要問我 VIM 比較好用還是 Android Studio 比較好 更不要問我 Linux Android 怎麼裝?
真正的主角程式
上次寫到主程式 MainActivity.java, 他會去執行 MainFragment.java, 所以 MainFragment 才是我們主要要進入的主題。 MainActivity 對應的是一個框框 (layout)而已。
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout ... android:id="@+id/MainLayout" tools:context="com.motor.sentinel.MainActivity"> <android.support.constraint.ConstraintLayout android:id="@+id/ContainerLayout" android:layout_width="0dp" android:layout_height="0dp" ..... android:layout_marginRight="8dp"> </android.support.constraint.ConstraintLayout> </android.support.constraint.ConstraintLayout>
上一篇的選單圖案, 才是搭配 MainFragment, 也就是說我們 把 fragment_main.xml 塞進 activity_main.xml , 瞭了嗎? 這不是程式技巧, 只是處理 UI / Android Fragment 架構的一種方法。不是你不會, 只是你習慣被教成 Activity 對應 Fragment。 技巧在哪裡? 其實沒有, 主要是 Android 強烈建議 盡量用 Fragment, 小咖如我們只好想辦法照辦。
其實如同上一篇講的, 如果你有辦法, 當然可以自己寫 API, 謎之音? 可能嗎? 當然不可能, 所以為了避免將來你的程式變成 deprecated, 還是不要自己找麻煩比較好, Android 還會事先告訴你, 還不錯啦。以下是 MainFragment的重點。
public void onClick(View v) { switch (v.getId()) { case R.id.main_start: DeviceListFragment fg = DeviceListFragment() .setTargetFragment(this, REQUEST_MAC_ADDRESS); FragmentManager manager = getActivity().getFragmentManager(); manager.beginTransaction() .replace(R.id.ContainerLayout, fg, fg.getTag()) .addToBackStack(null) .commit(); break; case R.id.main_diagnose: ... break; case R.id.main_troublecode: .... break; case R.id.main_information: break; case R.id.main_config: getFragmentManager().beginTransaction() .replace(R.id.ContainerLayout, new ObdConfigFragment()) .addToBackStack(null) .commit(); break; } }
public void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { case REQUEST_MAC_ADDRESS: bluetoothMac = data.getStringExtra(REQUEST_EXTRA_MAC_ADDRESS_STRING); new ObdConfig(getActivity()).saveMacAddress(bluetoothMac); isOnSelected = true; break; case REQUEST_ENABLE_BT: if (resultCode == Activity.RESULT_OK) { start.setEnabled(true); configuration.setEnabled(true); } else { Toast.makeText(getActivity(), R.string.bt_not_enabled_leaving, Toast.LENGTH_SHORT).show(); getActivity().finish(); } break; } }
這裡有兩個方法,任何一種都可以,不要太拘泥。main_start 是一種呼叫 DeviceListFragment.java 的方式。 main_config 則是另一種方式,你自己決定。至於 REQUEST_MAC_ADDRESS 是傳遞 Fragments 之間的法則, 如果你有順便參考 Android 提供的 BluetoothChat 範例,你會發現不一樣。
Android 規範 Activity 使用 Intent 呼叫 Calling 新的(下一個) Activity, 同時可夾著參數互相傳遞, 而 REQUEST_ENABLE_BT,REQUEST_MAC_ADDRESS 之類的,就是參數。但是我們是呼叫下一個 Fragment, 所以我們沒有 直接 使用 Intent, 而是被 Android 包起來了。
邁向下一步, 藍牙 API 的使用。
留言
張貼留言