J哥---------北京Android各招聘公司面試實戰總結2,---------android

來源:互聯網
上載者:User

J哥---------北京Android各招聘公司面試實戰總結2,---------android


 接上一篇 往下寫 http://blog.csdn.net/u011733020/article/details/45998861  ,   非常感謝在上一篇中給我指出問題的兄弟們。


面試公司:五道口  某公司面試時間:5月27日 11:00 AM.面試過程:                感覺公司還是挺有活力的的,進去填了申請表,人事就跟我聊了下 從上家離職原因(找工作 要準備怎麼回答這個問題,最好能找一些客觀因素,不要說 感覺以前公司不好。。。)  隨後 就是 android 技術 跟我面試。大概面試了 四十分鐘吧。慣例 總結了一下 有六七個問題,這個技術水平比較高,問得問題 有幾個我開發中都沒有遇到過。這次面試感覺 沒戲。。。    不過 失敗乃成功之父。不氣餒

面試官01問:解析json。類似這樣的 {
    "11:00": "0",
    "12:00": "0",
    "13:00": "0",
    "14:00": "0",
    "15:00": "0",
    "16:00": "0",
    "17:00": "0",
    "18:00": "0",
    "19:00": "0",
    "20:00": "0",
    "21:00": "0",
    "22:00": "0 "
}
 這個平時開發中沒碰到這種情況,自己也懶,沒有看還有什麼解析方法 說以當時只是說,解析json  源碼 其實跟解析xml 類似 都是 遍曆每一級,存到map集合中。知道應該有方法可以取到,但是 卻沒有想到 通過iterator。
J哥回答:這裡 當時沒能回答上方法,回來 看過解析json 的源碼 其實就是  存到一個HashMap<key,value>集合中
其實解析很簡單  就是先轉成JsonObject    然後拿到迭代器, 遍曆集合就可以取到 value。代碼很簡單
try {obj = new JSONObject(json);    Iterator iterator = obj.keys();while(iterator.hasNext()){Object next = iterator.next();// 擷取到 key obj.get(iterator.next().toString());// 擷取到 value}} catch (JSONException e) {// TODO Auto-generated catch blocke.printStackTrace();}
平時不在意 ,關鍵時刻掉鏈子!!!
面試官01問:Listview 如果有多種類型的 item ,怎麼實現。


J哥回答:這個問題,被問到的機率還是挺大的,自己以前 開發也沒遇到這樣的需求,也沒有去瞭解,所以回答的都不是很好。這裡 我回來尋找資料,才發現,google 開發人員 已經 考慮到這種情況,做了相應的支援,所以listview 本身是支援item 多type的。通常我們在使用listview  給 listview 適配資料的時候,用到adapter,以及 四個方法 getCount  getItem  getItemId  getView,那麼 在我們 多type  的item 時候,我們需要去複寫 兩個方法  getItemViewType   getViewTypeCount, 著兩個方法的的意思是
getViewTypeCount:

Returns the number of types of Views that will be created bygetView. Each type represents a set of views that can be converted ingetView. If the adapter always returns the same type of View for all items, this method should return 1.

This method will only be called when when the adapter is set on the theAdapterView.

Overrides: getViewTypeCount() in BaseAdapter
Returns:
The number of types of Views that will be created by this adapter
意思是 返回  getview 時 產生的 item 的 類型的個數,如果 我們的listview 中所有的item 只有一種類型 ,那麼我們不需要複寫這個方法,這個方法 當我們給listview  setAdapter 的時候 被調用。
因為 可以在baseAdapter  中發現  ,預設值 就是 1.
 public int getViewTypeCount() {        return 1;    }

另一個方法  getItemViewType   

Get the type of View that will be created by getView for the specified item.

Specified by: getItemViewType(...) inAdapter
Parameters:
position The position of the item within the adapter's data set whose view type we want.
Returns:
An integer representing the type of View. Two views should share the same type if one can be converted to the other in getView. Note: Integers must be in the range 0 to getViewTypeCount - 1. IGNORE_ITEM_VIEW_TYPE can also be returned
這個方法 返回 將要被 getview 建立的 item的 類型 。
返回值  範圍 0   ~~~~  到 類型type-1。


就是 這兩個關鍵的方法,要想我們實現多type 我們就要實現這兩個方法。

效果就是這樣子。
代碼實現 跟單一 item 唯一的區別 就在上述兩個方法 和 getview 方法中增加了判斷當前類型。下面Adapter中部分代碼
@Overridepublic View getView(int position, View convertView, ViewGroup parent) {int type = list.get(position).type;int itemViewType = getItemViewType(position);System.out.println("type===itemViewType"+(itemViewType==type));if(getItemViewType(position)==0){convertView =inflater.inflate(R.layout.item01_layout, parent, false);return convertView;         }else if(getItemViewType(position)==1){convertView =inflater.inflate(R.layout.item02_layout, parent, false);return convertView;}else{convertView =inflater.inflate(R.layout.item03_layout, parent, false);return convertView;}}@Overridepublic int getItemViewType(int position) {System.out.println("getItemViewType-------------------------------"+list.get(position).type);return list.get(position).type;}@Overridepublic int getViewTypeCount() {return maxType;}

 上面這裡 並沒有考慮過 convertview 的複用, 但是如果 有很多條的話,我們就不能這麼簡單的用了,要複用的話,我們要分別判斷 type類型,和 convertview 去實現複用,  這裡如果type 很多 複用的話,在getview 方法裡面要寫很多 判斷,假如 type==0 inflate 一個layout01,type==2 inflate  一個layout02....假如有十個 那麼 我們的getview方法裡要分別判斷 十次type 而且還要判斷 convetview==null,所以 類型多了的話,這個方法寫起來邏輯 可讀性都不好, 然而我有沒想到什麼好辦法,網上搜了點資料,這個感覺還是不錯的,用這種方式 雖然 要寫很多類,但是感覺不用把所有的代碼都寫在一個getview中。如果 有什麼好方法 可以一起分享出來。 listview 多type 複用 convertview 的解決方案

面試官01問:可以手動縮放的圖片 怎麼去實現。


J哥回答:由於 自己展示中的項目用到了 開源的  PhotoView, 所以 被問到自己實現。當時自己也沒有看 源碼,只是知道類似的,touchevent,知道 兩點觸摸時間,那是關於圖片 拖拽的, 實現的關鍵 就是 touch 時間的監聽,對於 手指按下, 手機移動,手指離開的監聽,記錄初始的xy ,以及離開時的 xy,進行相應的縮放,在onlayout  ondraw.  關於 photoview 的分析,自己找了些資料,這裡有一篇分析,感興趣的可以看一下,個人感覺還不錯。地址。 面試官01問:ImageLoader  源碼 分析


J哥回答: 開發中,多多少少都能接觸到非同步載入圖片,大家知道 universalImageLoader (github 地址 https://github.com/nostra13/Android-Universal-Image-Loader)載入圖片 可以有效地防止 因為圖片導致的oom。由於是開源,封裝的不錯,所以 一般項目中 都直接拿過來用,關於imageloader 的使用方法 這裡就不介紹了, 大體思路肯定 是 使用了緩衝,在保證效率的前提下 合理節約資源, 一般第一次載入 都是從網路載入,然後判斷是不是要儲存在本地,順便將圖片在記憶體儲存一下。 原理 這張圖 表達的比較清楚
使用方法 一般是  
ImageLoader.getInstance().displayImage(picurl, imageview);//傳入 圖片url 和 imageview 對象即可



這個ViewAware 對象  裡面 有一個 weakReference, 是的。 圖片在記憶體中就是 通過這個 弱引用緩衝的。

Implements a weak reference, which is the middle of the three types of references. Once the garbage collector decides that an objectobj is is weakly-reachable, the following happens:

  • A set ref of references is determined. ref contains the following elements:
    • All weak references pointing to obj.
    • All weak references pointing to objects from which obj is either strongly or softly reachable.
  • All references in ref are atomically cleared.
  • All objects formerly being referenced by ref become eligible for finalization.
  • At some future point, all references in ref will be enqueued with their corresponding reference queues, if any.
Weak references are useful for mappings that should have their entries removed automatically once they are not referenced any more (from outside). The difference between a SoftReference and a WeakReference is the point of time at which the decision is made to clear and enqueue the reference:
  • A SoftReference should be cleared and enqueued as late as possible, that is, in case the VM is in danger of running out of memory.
  • A WeakReference may be cleared and enqueued as soon as is known to be weakly-referenced. 
上面 是對於weakreference 的注釋
   WeakReference實現了一個弱引用,弱引用是三種引用(StrongReference、WeakReference、SoftReference)中的一個。一旦記憶體回收行程判定一個對象是是弱擷取(對象可擷取程度分為五種strongly reachable,softly reachable、weakly reachable、phantomly reachable、unreachable),則下列情況發生:
計算一組引用的ref,ref包括下列元素:
所有指向obj的弱引用
所有指向objects的弱引用,objects是軟擷取對象或者是強擷取對象
在ref中的所有引用被自動刪除
所有以前被ref引用的對象都符合終止條件的對象(become eligible for finalization)
在未來的某個時間,所有的在ref中的引用將被放入合適的引用隊列中
弱引用對那些映射,這些映射中的實體的引用一旦被不存在這些實體將被自動刪除。弱引用和軟引用的區別是清空和將加入排隊的時間點不同:
一個弱引用應該儘可能晚的被清除和排入佇列,那是因為如果記憶體不足是vm將是危險的
弱引用對象是一旦知道引用的是弱擷取對象就會被清除和入隊。
就是 在 JVM 記憶體不足的時候 GC 會優先回收這個 設定了 WeakReference 的對象。對於weakreference 的理解 還可以看下這篇文章 http://wiseideal.iteye.com/blog/1469295在繼續看Display 方法 
public void displayImage(String uri, ImageAware imageAware, DisplayImageOptions options,ImageLoadingListener listener, ImageLoadingProgressListener progressListener) {checkConfiguration();if (imageAware == null) {throw new IllegalArgumentException(ERROR_WRONG_ARGUMENTS);}if (listener == null) {listener = defaultListener;}if (options == null) {options = configuration.defaultDisplayImageOptions;}if (TextUtils.isEmpty(uri)) { //<span style="color:#ff0000;"> 判斷傳入的地址是否為空白</span>engine.cancelDisplayTaskFor(imageAware);listener.onLoadingStarted(uri, imageAware.getWrappedView());if (options.shouldShowImageForEmptyUri()) {//  <span style="color:#ff6666;">是否設定了預設的圖片</span>imageAware.setImageDrawable(options.getImageForEmptyUri(configuration.resources));} else {imageAware.setImageDrawable(null);}listener.onLoadingComplete(uri, imageAware.getWrappedView(), null);//<span style="color:#ff0000;">載入完成的回調</span>return;}ImageSize targetSize = ImageSizeUtils.defineTargetSizeForView(imageAware, configuration.getMaxImageSize());String memoryCacheKey = MemoryCacheUtils.generateKey(uri, targetSize);engine.prepareDisplayTaskFor(imageAware, memoryCacheKey);listener.onLoadingStarted(uri, imageAware.getWrappedView());Bitmap bmp = configuration.memoryCache.get(memoryCacheKey);if (bmp != null && !bmp.isRecycled()) {L.d(LOG_LOAD_IMAGE_FROM_MEMORY_CACHE, memoryCacheKey);if (options.shouldPostProcess()) {ImageLoadingInfo imageLoadingInfo = new ImageLoadingInfo(uri, imageAware, targetSize, memoryCacheKey,options, listener, progressListener, engine.getLockForUri(uri));ProcessAndDisplayImageTask displayTask = new ProcessAndDisplayImageTask(engine, bmp, imageLoadingInfo,defineHandler(options));if (options.isSyncLoading()) {displayTask.run();} else {engine.submit(displayTask);}} else {options.getDisplayer().display(bmp, imageAware, LoadedFrom.MEMORY_CACHE);listener.onLoadingComplete(uri, imageAware.getWrappedView(), bmp);}} else {if (options.shouldShowImageOnLoading()) {imageAware.setImageDrawable(options.getImageOnLoading(configuration.resources));} else if (options.isResetViewBeforeLoading()) {imageAware.setImageDrawable(null);}ImageLoadingInfo imageLoadingInfo = new ImageLoadingInfo(uri, imageAware, targetSize, memoryCacheKey,options, listener, progressListener, engine.getLockForUri(uri));//將資訊儲存到這個對象中LoadAndDisplayImageTask displayTask = new LoadAndDisplayImageTask(engine, imageLoadingInfo,defineHandler(options));// 產生下載任務if (options.isSyncLoading()) { //下載displayTask.run();} else {engine.submit(displayTask);}}}

代碼太多,不一一貼出來了,在下載圖片的task 方法中,會 做一些 安全執行緒的同步,還有就是判斷本地 記憶體 有沒有以前下載好了,有的話直接拿過來用,沒有 去下載 然後試著儲存在磁碟緩衝中
private boolean downloadImage() throws IOException {InputStream is = getDownloader().getStream(uri, options.getExtraForDownloader());if (is == null) {L.e(ERROR_NO_IMAGE_STREAM, memoryCacheKey);return false;} else {try {return configuration.diskCache.save(uri, is, this);} finally {IoUtils.closeSilently(is);}}}

面試官01問: 大圖片 載入 oom 問題


J哥回答: 對於大圖片,直接載入給Imageview  容易出現 OOM 異常,那麼我們就要對其進行壓縮, 壓縮原理,根據手機解析度 去壓縮首先擷取手機解析度:
  WindowManager windowManager= (WindowManager)getSystemService(WINDOW_SERVICE);        Display display= windowManager.getDefaultDisplay();        height = display.getHeight();        width = display.getWidth();
然後 計算圖片的寬度高度,根據比例壓縮 在顯示 圖片
public void  calImageView(){//        Log.i("file","ImageWidth:"+ImageWidth);//        Log.i("file","ImageHeight:"+ImageHeight);        BitmapFactory.Options options=  new  BitmapFactory.Options();        options.inJustDecodeBounds=true;//        bitmap=null        String path="";// 對應圖片的 地址        BitmapFactory.decodeFile(path, options);        int ImageWidth= options.outWidth;        int ImageHeight= options.outHeight;        System.out.print("ImageWidth:" + ImageWidth);        System.out.print("ImageHeight:"+ImageHeight);        int scaleX=ImageWidth/width;        int scaleY=ImageHeight/height;        int scale=1;        if(scaleX>scaleY & scaleY>=1){            scale=scaleX;        }        if(scaleY>scaleX & scaleX>=1){            scale=scaleY;        }        //解析圖片        options.inJustDecodeBounds=false;        options.inSampleSize=scale;       Bitmap bitmap= BitmapFactory.decodeFile("/storage/emulated/a.jpg", options);        iv.setImageBitmap(bitmap);//        ByteArrayOutputStream baos = null ; 另一種壓縮方式//        baos = new ByteArrayOutputStream();//        bitmap.compress(Bitmap.CompressFormat.JPEG, 30, baos);        }


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.