Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android面試准備 第一天 第2-4例

Android面試准備 第一天 第2-4例

編輯:關於Android編程

2、如果有個100M大的文件,需要上傳至服務器中,而服務器form表單最大只能上傳2M,可以用什麼方法。

個人理解:所謂表單最大只能上傳2M,是不是指一個表單中附件只能上傳最大2M,如果是的話,現在要求上傳100M,為什麼不直接

把附件上傳大小設置為100M就可以了,除此菜鳥的我,並想不出這個題目究竟要考核面試者的什麼知識點。

標准答案:這個問題不是很明確我覺得,首先來說使用http協議上傳數據,特別在android下,跟form沒什麼關系。傳統的在web中,在form中寫文件上傳,其實浏覽器所做的就是將我們的數據進行解析組拼成字符串,以流的方式發送到服務器,且上傳文件用的都是POST方式,POST方式對大小沒什麼限制。回到題目,可以說假設每次真的只能上傳2M,那麼可能我們只能把文件截斷,然後分別上傳了。

二次理解:因為android程序中頁面都是活動和碎片,跟form沒有什麼關系,只有一個類似form的布局tablelayout,但跟form字面上都不是一回事所以android並不存在form表單說法,應該是指html中form表單,那麼表單附件上傳中首先把數據解析字符串文件以IO流的方式上傳到服務器,而且並沒有上傳限制,如果有話,應該是什麼原因,防止長時間占用服務器,降低效率,那麼把文件截斷上傳還有意義嘛,這個問題不具備普遍性,所以不進行深究。

3、內存溢出和內存洩漏有什麼區別?何時會產生內存洩漏?內存優化有哪些方法?

個人理解:不知道他們的區別,以為是同一件事情,比如內存中創建的對象過多時,導致內容空間不夠,會產生該現象;及時關閉不必要的

資源,如數據庫連接、IO流等,另外可以通過代碼重構,盡可能減少對象的創建數量。

標准答案:

內存溢出通俗理解就是軟件(應用)運行需要的內存,超出了它可用的最大內存。

內存洩漏就是我們對某一內存空間的使用,使用完成後沒有釋放。

內存優化:Android中容易內存溢出的部分,就是圖片的加載,我們可以使用圖片的壓縮加上使用LruCache緩存的目的來控制圖片所能夠使用的內存。還有對於比較耗資源的對象及時的關閉,例如Database Conn , 各種傳感器, Service等等。

二次理解:內存溢出指內存超出它可用的最大內容,而內存洩露則特指使用的資源沒有釋放,而內容中容易內存溢出的就是存儲加載,使用壓縮和緩存的方式,而內存洩露則需要及時關閉資源,比如數據連接、服務等。概念話的內容,並沒有實際的參照價值,因為暫時沒有學習圖片加載的使用

 

4、AsyncTask使用在哪些場景?它的缺陷是什麼?如何解決?

個人理解:AsyncTask也是一種多線程的通信機制,但是AsyncTask並不需要去創建新的線程,把需要的操作直接定義在該對象的方法中就可以了,具體什麼方法忘記,在第一行代碼因為學習的Handler機制所以並沒有加深對AsyncTask的理解,至於它的缺陷和解決方式更是不清楚了。

標准答案:

AsyncTask 運用的場景就是我們需要進行一些耗時的操作,耗時操作完成後更新主線程,或者在操作過程中對主線程的UI進行更新。

缺陷:AsyncTask中維護著一個長度為128的線程池,同時可以執行5個工作線程,還有一個緩沖隊列,當線程池中已有128個線程,緩沖隊列已滿時,如果此時向線程提交任務,將會拋出RejectedExecutionException。

解決:由一個控制線程來處理AsyncTask的調用判斷線程池是否滿了,如果滿了則線程睡眠否則請求AsyncTask繼續處理。

二次理解:

AsyncTask與Handler機制類似,即異步消息處理機制,所謂異步,即是並行執行的意思,而多線程就是相互獨立"同時"在運行,而AsyncTask相對與Handler機制的不同,他對Handler進行了封裝,在使用時不需要走Handler的流程,直接在doInBackground()中定義相關方法,系統自動創建新子線程去執行。AsyncTask與Handler機制是功能是相似的,可以用來在子線程中更新UI,或者下載耗時比較久的操作,比如下載文件因為主線程頁面響應,即一個操作點擊後,頁面針對該操作做出反應的時間過長,那麼Android系統會認為是不友好的行為,該程序會直接崩潰。關於標准答案中AsyncTask可以維護一個長度為128的線程池,究竟是什麼概念,我可以理解為可以容納128線程嘛?但是我能想象到的就是手機App目前都是客戶端本地的模式,即C/S模式,基本不存在一個用戶在一個應用下打開128個下載內容,但不排除這個情況,然後執行5個工作線程的又是什麼意思,與128是否沖突,還是概念上有什麼差別(解答:所謂可以執行5個工作線程,長度為128的線程池,好比迅雷下載,你可以開啟128個下載任務,但是它只支持5個任務正在下載,超出的任務將進入緩沖區域,只有當前5個任務完結時,才會從緩沖區域獲取並執行新的任務,而超出128個任務時,則提示拒絕執行異常)。關於標准答案開辟一個子線程去監控線程緩沖區是否已滿,如果滿了,則讓請求的線程的睡眠,但是睡眠的時間怎麼設定?怎麼實現線程緩沖區空閒時,睡眠停止的工作。暫時還沒有找到更加詳細資料。

使用介紹:由於本人對AsyncTask的使用沒有更多的了解,所以這裡會講AsyncTask的簡單介紹和使用辦法。

特點1:AsyncTask,是一個抽象類,所以要使用必須要創建一個子類就繼承它。

特點2:AsyncTask,必須指定三個泛型參數,所謂類的泛型參數,可以認為是java的一種指定類中所關聯對象的具體類型做法,這種做法的意義就是可以限制或者是明確了對象類型的范圍,可以讓編譯器根據定義的泛型更加明確判定到內部代碼的正確性,這是解決程序執行時多態轉型異常的一種手段。參數列表為,分別指傳入的參數,可以在後台任務中使用;可以選擇在前台顯示當前進度,這裡指定進度單位;任務執行完畢後,如果需要對結果進行返回,則這裡指定返回指的類型。

最簡單的形式:class DownloadTask extendsAsyncTask,見第一行代碼,Void表示不傳入參數。

特點3:AsyncTask方法介紹:

  1. onPreExecute:顧明思義,就是在執行子線程任務之前調用,不如我們要下載一個文件,可以在這裡顯示一個進度框,因為這是在主線程中執行的。doInBackground(Params):該方法就是後台操作的內容,系統會自動生成一個子線程去執行該方法中的內容,一些耗時的內容,比如下載一個文件的代碼。該方法的參數和返回值類型和泛型中第二、三個相對應。因為這裡是在子線程中執行的,如果需要對主線程中進度框更新,則需要調用publicProgress(Progress),該方法的調用自動引入第三個方法onProgressUpdate(Progress)的調用。onProgressUpdate(Progress),它的調用取決於doInBackground(Params)中是否調用了publicProgress(Progress)的方法,它的Progress參數也來源於publicProgress(Progress)中的參數,該方法其實就是在主線中去更新進度。onPostExcuteResult(Result),該方法將在doInBackground(Params)執行完畢後執行,其中Result參數也來源於doInBackground方法的返回值,該方法可以執行對主線程的中UI的操作,比如關閉onPreExecute中創建的進度框,提示文件下載完成等。excute(Params),在主線程創建這個AsyncTask子類的對象後,調用改方法,將啟動異步執行的操作。  

    代碼示例1:

    UIActivity.xml

    
    
    package com.noodles.uipractice; import android.os.AsyncTask; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.Button; import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.URL; import java.net.URLConnection; public class UIActivity extends AppCompatActivity { private TextView tv; private Button btn; private ProgressBar progressBar; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_ui); tv = (TextView) findViewById(R.id.tv); progressBar = (ProgressBar) findViewById(R.id.progress_bar); btn = (Button) findViewById(R.id.send_text); /** * 4、給Button定義個點擊事件,就是啟動AsyncTask * 其中execute的參數Params內容會自動傳遞給doInBackground的字符串數組類型的參數 */ btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new MyAsyncTask().execute("http://www.baidu.com"); } }); } /** * 1、在主活動中中定義一個內部類MyAsyncTask繼承AsyncTask * 當然也可以不以內部類的形式,比如單獨定義一個類或者用匿名內部類 * 不覺哪種定義方式更具有優勢,因為單獨定義分離後而代碼結構更加清晰。 * 而匿名內部類和內部類更加貼近業務一體性。 */ class MyAsyncTask extends AsyncTask { /** * 2、復寫doInBackground方法,該方法會開辟一個子線程去執行其中的代碼 * 一般都是進行一些耗時的操作,這裡可以去獲取百度首頁的內容 *

    * String... params形式的參數列表,可以看做String[] params */ @Override protected String doInBackground(String... params) { BufferedReader br = null; try { //首先把百度的首頁地址www.baidu.com,封裝成URL,就比如在浏覽器中用鍵盤輸入www.baidu.com URL url = new URL(params[0]); //調用URL的openConnnection方法,就好比在浏覽器的點擊了回車 URLConnection connection = url.openConnection(); //如果沒有下面這行話,則默認是調用GZIP的壓縮技術,getContentLength()返回的就是-1 connection.setRequestProperty("Accept-Encoding", "identity"); //connection.connect(); long Total = connection.getContentLength(); /* 建立連接以後,形成了socket通道,以IO流的方式形成數據的流轉,所謂IO流可以看作是計算機 * 所有媒介進行數據流轉的一種固定形式,只是剛好起了一個名字叫IO流。而我們建立連接後 * 默認是以get的方式想百度服務器請求數據,可以請求返回一個字節輸入流,即InputStream,而我們知道,返回 * 的內容都是字符串,所有可以通過InputStreamReader,把字節流轉換成字符流,因為java為字符流提供的方式 * 更加易用,同時java提供一個緩存區的BufferReader,本質就是數組,可以把單獨的字符用大的容器裝載後 * 再進行傳輸,這樣減少了傳輸的回合,提高效率 * */ //調用connection的getInputStream可以獲取服務器返回的字符流 InputStream inputStream = connection.getInputStream(); //調用InputStreamReader對象,可以把字節流轉換為字符流 InputStreamReader isr = new InputStreamReader(inputStream); //用BufferReader去裝載字符流 br = new BufferedReader(isr); //調用BufferedReader的方法,更便捷的獲取請求的內容 //定義一個字符串變量用來接收BufferedReader的readLine方法讀取的每一行數據 String line; StringBuffer stringBuffer = new StringBuffer(); int count = 0; while ((line = br.readLine()) != null) { //讀取的每一行數據都放在stringBuffer中 stringBuffer.append(line); /** * 5、對UI中已經定義的進度條進行更新,直接調用publishProgress方法 * 但是裡面的參數類型必須和AsyncTask中聲明的泛型一致,即Float */ count += line.length(); Integer value = (int) (count / (float) Total * 100); publishProgress(value); Thread.sleep(1000); } return stringBuffer.toString(); } catch (Exception e) { e.printStackTrace(); } finally { try { if (br != null) { br.close(); } } catch (IOException e) { e.printStackTrace(); } } //如果執行期間發生異常,則返回null return null; } /** * 3、復寫onPostExecute,其中它的參數值來源於doInBackground的返回值 * 該方法可以更新主線程的UI,把返回的內容直接顯示在主線程的TextView上 */ @Override protected void onPostExecute(String s) { tv.setText(s); Toast.makeText(UIActivity.this, "數據下載結束", Toast.LENGTH_SHORT).show(); } @Override protected void onProgressUpdate(Integer... values) { progressBar.setProgress(values[0]); } } }



    
    

    AndroidManifest.xml

     

    <!--{cke_protected}{C}%3C!%2D%2D%3Fxml%20version%3D%221.0%22%20encoding%3D%22utf-8%22%3F%2D%2D%3E-->
    <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.noodles.uipractice">
    
        <uses-permission android:name="android.permission.INTERNET">
        <application android:allowbackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsrtl="true" android:theme="@style/AppTheme">
            <activity android:name=".UIActivity">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN">
    
                    <category android:name="android.intent.category.LAUNCHER">
                </category></action></intent-filter>
            </activity>
        </application>
    
    </uses-permission></manifest>

    點擊前:

    \

    點擊後:


    \

    總結:AsyncTask是Android提供另一種異步信息處理機制,明確的說就是多線程間的通訊,有別於Handler機制地方,它是Handler的封裝所以在使用上面

    更加的便捷,首先我們需要繼承該類,復寫裡面的方法,必須復寫就是doInBackground(Params),該方法會創建一個子線程去執行方法中代碼,所以一般用來

    執行耗時的操作,比如下載文件。然後我們需要創建該子類的對象,並調用execute(Params)方法,其中參數Params由外部傳入,該參數會自動傳入oInBackground(Params)的參數,並且在AsyncTask的第一個泛型參數Params指定它的類型,第二泛型參數progress是指AsyncTask在doInBackground(Params)方法中可以調用publishProgress(progress),需要指定具體類型的值progress,系統會轉而調用onProgressUpdate(progress)同時傳入該數值,這個方法可以對主線程的UI進行更新,一般是用作更新進度條。第三個參數Result,是指doInBackground(Params)方法執行後需要返回一個值,接著系統會調用onPostExecute(Result),並把返回指傳入這個方法,這個方法是執行一些收尾工作,把信息反饋給用戶,比如更新主線程的UI,告訴用戶下載已經完成等。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved