工作第三週:之前的隨筆

幾個需求:

假如我們只有兩個activity,如何實現界面跳轉

       假如界面現在需要只能有兩個activity,那麼也想實現界面的跳轉該怎麼做?如果用fragment的話那每次沒有跳轉的動作。如何實現?
後臺我想了一下我們清淡文件中註冊兩個activity。在fragment切換的時候其實是通過activity的切換,但是把fragment的名字穿過去,通過反射的方式調用。

Intent intent = new Intent(ChartActivity.this,ContainActivity.class);
intent.putExtra("netfragment",clazz.getCanonicalName());
Log.e("tag","======"+clazz.getCanonicalName());
startActivity(intent);


Intent intent = getIntent();
String netfragment = intent.getStringExtra("netfragment");
//通過反射調研fragment
try {
    Fragment  f = (Fragment) Class.forName(netfragment).newInstance();
    getSupportFragmentManager().beginTransaction().add(R.id.fl_contain,f).commit();
} catch (InstantiationException e) {
    e.printStackTrace();
} catch (IllegalAccessException e) {
    e.printStackTrace();
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}

       其實這時候內存中是有很多activity實例的,但是隻有一種activity類,這樣避免了多次的在清單文件中註冊。

okhttp支持HTTPS怎麼配置:

       其實setCertificates(input stream),讀取證書

    private void setCertificates(InputStream... certificates) {
        try {
            CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
            keyStore.load(null);
            int index = 0;
            for (InputStream certificate : certificates) {
                String certificateAlias = Integer.toString(index++);
                keyStore.setCertificateEntry(certificateAlias, certificateFactory.generateCertificate(certificate));
                try {
                    if (certificate != null)
                        certificate.close();
                } catch (IOException e) {

                }
            }
            SSLContext sslContext = SSLContext.getInstance("TLS");
            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            trustManagerFactory.init(keyStore);
            sslContext.init(null, trustManagerFactory.getTrustManagers(), new SecureRandom());
            //這裏初始化httpClient
            retrofit = new Retrofit.Builder()
                    .baseUrl(url)
                    .client(new OkHttpClient.Builder()
                            .sslSocketFactory(sslContext.getSocketFactory())
                            .build())
                    .addConverterFactory(GsonConverterFactory.create())
                    .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                    .build();
            service = retrofit.create(YisudaService.class);

        } catch (Exception e) {
            e.printStackTrace();
        }


    }
調用的話:
setCertificates(this.getResources().openRawResource(R.raw.tomcat));

activity管理棧的好處

public synchronized void addActivity(Activity activity) {

   if (activityStack == null) {
      activityStack = new Stack<Activity>();
   }

   Log.v(TAG, activity.getClass().getSimpleName() + "===>>>>>> 添加新的實例成功");
   activityStack.add(activity);

   MobclickAgent.setScenarioType(activity, MobclickAgent.EScenarioType.E_UM_NORMAL);

}

       每次添加的一個activity都用一個強引用引用這樣可以保證處於stop,pause的activity不至於沒存不足的時候被系統銷燬掉。

狀態的標示,杜絕用true,false

       
爲什麼開發中杜絕用true,false作爲標識?
在我們平時的開發中經常會遇到根據某個狀態進行不同的邏輯操作,很多時候我們爲了方便直接使用true,false,但是這樣有個問題,本來自可能只有兩個狀態(比如,已掃描,未掃描),隨着業務的拓展,我們的狀態越來越多,現在加了“強掃描”狀態,由於之前用true,false區分的,現在又多了狀態,我們得把以前的代碼全部修改,任務量極大,有的同學或者直接用“0”,“1”,“2”加以區分,這樣相比於前者是有進步,但是你不覺得這麼對換個人維護是個成本極高的事嗎?鬼知道你“0”,“1”,“2”是什麼意思。有經驗的開發相比於初級開發區別在於,開發中我們就應該儘量避規這些可能會潛在並稍微注意就可以避規的風險,
如果不這麼用,那用什麼比較好呢?
我給的建議是用枚舉,儘管移動端不像服務器端那麼不考慮內存,Google也建議少使用枚舉(具體爲什麼少使用枚舉請看我另一篇博客http://blog.csdn.net/u012070360/article/details/59529535,每個枚舉項都會被聲明成靜態變量),但是那點內存與代碼的質量,拓展延伸,健壯,美觀,作權衡我還是更傾向於用“不被看好的”枚舉。

 public enum Status {
        noScan,
        hasScan,
        strongScan;

        public static String getName(Status status) {
            return getName(status.ordinal());
        }

        public static String getName(int id) {
            if (noScan.ordinal() == id) {
                return "未掃";
            } else if (hasScan.ordinal() == id) {
                return "已掃";
            } else if (strongScan.ordinal() == id) {
                return "強掃";
            }
            return "";
        }

    }

使用的時候我們只需要這麼設置,簡單,直觀,健壯,可拓展都得到了提升。。。

 entity.setScanFlag(PartnerLoadingEntity.Status.noScan.ordinal());

什麼是4k對齊,android打包過程術

先弄清楚一個概念
什麼叫“在4個字節邊界上對齊”,這個就是android應用程序在安裝到系統的時候編譯器會以4個字節作爲一個單位進行讀取的結果,cpu能對變量進行更高更快的訪問,這樣的話,效率相比較未對齊要高。

Android SDK中包含一個“zipalign”的工具,它能夠對打包的應用程序進行優化。在你的應用程序上運行zipalign,使得在運行時Android與應用程序間的交互更加有效率。因此,這種方式能夠讓應用程序和整個系統運行得更快。我們強烈推薦在新的和已經發布的程序上使用zipalign工具來得到優化後的版本——即使你的程序是在老版本的Android平臺下開發的。這篇文章將描述zipalign如何有助於性能改善以及如何使用它來優化你的app。
在Android中,每個應用程序中儲存的數據文件都會被多個進程訪問:安裝程序會讀取應用程序的manifest文件來處理與之相關的權限問題;Home應用程序會讀取資源文件來獲取應用程序的名和圖標;系統服務會因爲很多種原因讀取資源(例如,顯示應用程序的Notification);此外,就是應用程序自身用到資源文件。

從未對齊的apk中讀取資源比較慢且花費較多內存。最好的情況是,Home程序和未對齊的程序啓動得比對齊後的慢(這也是唯一可見的效果)。最壞的情況是,安裝一些未對齊資源的應用程序會增加內存壓力,並因此造成系統反覆地啓動和殺死進程。最終,用戶放棄使用如此慢又耗電的設備。

在Android中,當資源文件通過內存映射對齊到4字節邊界時,訪問資源文件的代碼纔是有效率的。但是,如果資源本身沒有進行對齊處理(未使用zipalign工具),它就必須回到老路上,顯式地讀取它們——這個過程將會比較緩慢且會花費額外的內存。

在Android中,當資源文件通過內存映射對齊到4字節邊界時,訪問資源文件的代碼纔是有效率的。但是,如果資源本身沒有進行對齊處理(未使用zipalign工具),它就必須回到老路上,顯式地讀取它們——這個過程將會比較緩慢且會花費額外的內存。
對於應用程序開發者來說,這種顯式讀取方式是相當便利的。它允許使用一些不同的開發方法,包括正常流程中不包含對齊的資源,因此,這種讀取方式具有很大的便利性(本段的原始意思請參考原文)。
遺憾的是,對於用戶來說,這個情況恰恰是相反的——從未對齊的apk中讀取資源比較慢且花費較多內存。最好的情況是,Home程序和未對齊的程序啓動得比對齊後的慢(這也是唯一可見的效果)。最壞的情況是,安裝一些未對齊資源的應用程序會增加內存壓力,並因此造成系統反覆地啓動和殺死進程。最終,用戶放棄使用如此慢又耗電的設備。
幸運的是,對應用程序中的資源作對齊操作很簡單:
· 使用ADT:
o 如果你使用導出嚮導的話,Eclipse中的ADT插件(從Ver. 0.9.3開始)就能自動對齊Release程序包。使用嚮導,右擊工程屬性,選擇“Android Tools” > “Export Signed Application Package…”。當然,你還可以通過AndroidManifest.xml編輯器的第一頁做到。
· 使用Ant:
o Ant編譯腳本(從Android 1.6開始)可以對齊程序包。老平臺的版本不能通過Ant編譯腳本進行對齊,必須手動對齊。
o 從Android 1.6開始,Debug模式下編譯時,Ant自動對齊和簽名程序包。
o Release模式下,如果有足夠的信息簽名程序包的話,Ant纔會執行對齊操作,因爲對齊處理髮生在簽名之後。爲了能夠簽名程序包,進而執行對齊操作,Ant必須知道keystore的位置以及build.properties中key的名字。相應的屬性名爲key.store和key.alias。如果這些屬性爲空,簽名工具會在編譯過程中提示輸入store/key的密碼,然後腳本會執行簽名及apk文件的對齊。如果這些屬性都沒有,Release程序包不會進行簽名,自然也就不會進行對齊了。
· 手動:
o 爲了能夠手動對齊程序包,Android 1.6及以後的SDK的tools/文件夾下都有zipalign工具。你可以使用它來對齊任何版本下的程序包。你必須在簽名apk文件後進行,使用以下命令:zipalign -v 4 source.apk destination.apk
· 驗證對齊:
o 以下的命令用於檢查程序包是否進行了對齊:zipalign -c -v 4 application.apk
我們極力推薦手動zipalign你的應用程序,並確保將最新對齊後的版本提供給用戶。此外,別忘了還有你的新應用程序也需要這麼做!


下面是參考某網友的:我覺得比較好,就拿來了

安卓的構建的流程
這裏寫圖片描述

主要有以下幾步:

主要的資源文件(layout, values 等)都被 aapt 編譯,並且在一個 R 文件中引用

  1. Java 代碼被 Java 編譯器編譯成 JVM 字節碼(.class 文件)
  2. JVM 字節碼再被 dex 工具轉換成 dalvik 字節碼(.dex 文件)
  3. 然後這些 .dex 文件、編譯過的資源文件和其他資源文件(比如圖片)會被打包成一個 apk
  4. apk 文件在安裝前會被 debug/release 的 key 文件簽名
  5. 安裝到設備

幾個注意點

上面的步驟中第一步注意是主要的資源文件,有些特別的資源文件就不會被編譯,比如 assets 目錄下的文件,raw 目錄下的文件還有圖片,都不會被編譯。只不過 raw 下的文件會在 R 文件裏生成 id

http://blog.csdn.net/luoshengyang/article/details/8744683

如果對 apk 正式簽名,還需要使用 zipalign 工具對 apk 進行對齊操作,這樣做的好處是當應用運行時會減少內存的開銷

通過上面的介紹可以看到,這麼複雜的構建過程如果需要人手動去完成未免太過殘忍,於是有了各種的構建工具。

Android 構建的舊愛:Ant, Maven

Ant 2000 年發佈,很快成爲 Java 項目最流行的構建工具。

Ant 的優點就是:
- 簡單、易學,不需要什麼特殊準備就能上手
- 基於過程式編程思想使得構建非常靈活
- 後來還能支持插件。

不足之處就是使用 XML 作爲腳本配置格式,除非是很小的項目,否則它的 XML 文件很快就大得無法管理。

Maven

Maven 也是使用 XML 作爲構建配置的文件格式,不過文件結構卻有了巨大的變化:

Ant 需要開發者將執行 task 所需的全部命令都列出來
而 Maven 依靠約定並提供現成的可調用的目標
不僅如此,Maven 更重要的一個進步是具備從網絡上自動下載依賴的能力(當然 Ant 後來通過 Ivy 也具備了這個功能),這革命性地改變了我們開發軟件的方式。

Maven 的缺點是:

依賴管理不能很好地處理相同庫文件不同版本之間的衝突(Ivy在這方面更好一些)
XML 作爲配置文件的格式有嚴格的結構層次和標準,定製化目標很困難
Maven 主要解決了依賴管理的問題,然而使用 XML 的錯誤使它重蹈覆轍,實際上用 Maven 很難寫出複雜、定製化的構建腳本,在大型項目中,它經常什麼“特別的”事還沒幹就有幾百行代碼,甚至不如 Ant。

前輩們在反省前兩種構建工具的錯誤之後,提出了 DSL (Domain Special Language, 領域專用語言)的概念,目標是設計一套能夠解決特定領域問題的語言。在構建這方面,DSL 的一個成功案例就是 Gradle。

2012 年發佈的 Gradle 深刻吸取前面幾位前輩的經驗和教訓,集大家之所成,做了很多改進。

Gradle 有約定優於配置的原則,即爲設置和屬性提供默認值,這使得它比 Ant 或者 Maven 更容易上手。

Gradle 構建腳本不再使用 xml ,而是使用基於 Groovy 的 DSL 進行書寫(Groovy 是一種基於 Java 虛擬機的動態語言,因此 Android 開發者看着會很熟悉),從而使得構建腳本比用 Ant 和 Maven 寫的更清晰、簡潔,下面是實現同樣目標的 Maven 代碼和 Gradle 代碼對比:

Gradle 既有 Ant 的強大和靈活,又有 Maven 的依賴管理,支持插件且易於使用。因此一推出就獲得廣泛關注,2013 年被 Google 選爲 Android Studio 的默認構建工具。

Gradle 設計的方式使得它可以很容易地擴展構建和插入到現有的構建過程中,Google 推廣 Gradle 和 Android Studio 時,目標是讓代碼複用、構建 variant、配置和定製構建過程變得更加簡單。

有人可能擔心是否需要專門去學習新語言 Groovy,《Gradle for Android》書中專門提到:

Groovy 代碼非常易讀,如果你學習過 Java,那麼學習 Groovy 的曲線不會陡峭。
如果你想構建自己的任務和插件,那麼對 Groovy 有更深層次的理解尤爲重要。
不過因爲 Groovy 是基於 Java 虛擬機的,所以你完全可以用 Java 或者其他基於 Java 虛擬機的語言來編寫你的自定義插件。
Gradle 的關鍵概念及構建生命週期

Gradle 中兩個關鍵的概念:項目和任務。

每個 build.gradle 構建腳本文件代表一個項目 project:
這裏寫圖片描述

上圖我並沒有使用 wrapper,是因爲當你運行 gradlew 命令時,gradle wrapper 會自動下載需要但是你沒有的 gradle 版本並使用。
這在多人協作時,很可能因爲別人修改了 gradle 版本、上傳到 Git,然後導致你運行命令時需要下載半天。

不過官方還是推薦使用 wrapper,畢竟這樣更穩定。

使用 gradle wrapper 以後,gradle wrapper 會爲每個項目下載一個 gradle 壓縮包,路徑在 \Users\yourname.gradle\wrapper\dists 裏:
這裏寫圖片描述

總結
Android Studio 佔領市場後,構建工具 Gradle 的地位無人能比,我們有必要學習、使用它來爲我們創造價值。

這篇文章對比 Ant 和 Maven 泛泛而談了 Gradle 的一些優點,在理解 Gradle 爲什麼會被使用、它有什麼優點之後,有助於我們後續深入學習 Gradle 的使用。

遇到的問題

Execution failed for task ‘:app:zipalignDevRelease’.

Process ‘command ‘/Users/zew/Library/Android/sdk/build-tools/24.0.0/zipalign” finished with non-zero exit value 1
在安卓打包的時候老是出現這個bug?
今天項目沒動什麼地方就出現了
Error:Execution failed for task ‘:app:zipalignDebug’. > Process ‘command ‘D:\sdk1\build-tools\23.0.1\zipalign.exe” finished with non-zero exit value 1錯誤,
我的解決方案:我是clean 在rebuild一下就解決了
網友解決方案:後來看網上的一些網友的問題是:
而且clean 也提示
Error:Execution failed for task ‘:app:clean’. > Unable to delete file:XXX錯誤
更新了sdk,換版本什麼的也沒用,
最後才發現 clean錯誤是因爲XXX文件被佔用,才報錯(之前因爲用到了debug.apk,所以這個文件被佔用)
value 1這個錯誤可以有很多原因導致,如果和clean錯誤同時出現,那很可能是XXX文件被佔用,
如果還不行就強殺調Java進程重啓as

如何判斷某個view是否是在界面可見

public class MainActivity extends AppCompatActivity {

    private VideoView vv;
    private ScrollView mScrollView;
    private TextView mTextView;
    private int mScreenHeight;
    private int mScreenWeight;
    private Rect mRect;
    private boolean isReady;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
        Point point = new Point();
        windowManager.getDefaultDisplay().getSize(point);
        mScreenHeight = point.y;
        mScreenWeight = point.x;
        System.out.println(mScreenHeight+"");
        System.out.println(mScreenWeight+"");
        initViews();
    }

    private void initViews() {
        mScrollView= (ScrollView) findViewById(R.id.sv);
        mTextView= (TextView) findViewById(R.id.tv1);
        mRect = new Rect(0,0,mScreenWeight,mScreenHeight );
        mScrollView.setOnScrollChangeListener(new View.OnScrollChangeListener() {
            @Override
            public void onScrollChange(View view, int i, int i1, int i2, int i3) {
                if(mTextView.getLocalVisibleRect(mRect)){
                    if (isReady) {
                        isReady=false;
                        System.out.println("控件在屏幕顯示範圍內");
                    }
                }else{
                    if (!isReady){
                        isReady=true;
                        System.out.println("控件在屏幕顯示範圍外");
                    }
                }
            }
        });
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章