點贊處理的一些小技巧

codelang發表於2018-09-13

今天來講一些平時用的小技巧,然後由此引申一些其他的小技巧。

點贊是我們平時業務開發最常接觸的,但如何更投巧的去做這塊,還需要細細的開動小腦筋,下面會有一些和平時開發的對比,慢慢品味吧

連續點贊網路請求處理

在我們處理點贊業務中,主要處理“贊”圖片的翻轉和結果的網路請求,按照我們常規操作的話,每一次點選,都會把結果告知伺服器,操作虛擬碼如下:

    boolean zanFlag = false;

    public void clickZan(View view) {
        if (zanFlag) {
            imgZan.setImageResource(R.drawable.zan_normal);
        } else {
            imgZan.setImageResource(R.drawable.zan_focus);
        }
        zanFlag = !zanFlag;
        //網路請求操作
        requestNet();
    }
複製程式碼

這麼看似乎是沒什麼問題,業務處理也是可行的,然後我們在網路請求這個部分做個日誌列印,模擬網路請求,然後來看下圖:

點贊處理的一些小技巧

當我們在開始部分緩慢的進行點贊時,似乎是沒有任何問題的,後面我開始瘋狂點選,不斷的產生網路的請求。假設,如何我瘋狂連續點選100次,最終的結果只是“讚了”或是“沒贊”,也就是隻有2個結果,為了這兩個結果,我們需要做100次網路請求,實數浪費。

從產品設計思路來思考,對於連續請求的處理,我們完全可以延時等待使用者停止瘋狂點選,然後將最後一次的結果作為最終結果再來上傳處理,避免了在瘋狂點選時頻繁請求。

順著這個思路來思考編碼,我們需要一個定時,即在使用者點選該按鈕時,延時這個定時等待使用者是否還會繼續點選,如果使用者在這個延時內還繼續點選,則取消之前的定時,重新傳送一個定時,直到使用者停止點選了,延時也到了,則在延時到了的回撥中去處理網路請求,這樣,可以省了很多無用網路請求,接下來,我們開始編碼

    Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            //網路請求操作
            requestNet();
        }
    };

    boolean zanFlag = false;
    private static final int DELAY_MESSAGE = 0x0429;
    private static final int delayTime = 500;
    
    public void clickZan(View view) {

        if (zanFlag) {
            imgZan.setImageResource(R.drawable.zan_normal);
        } else {
            imgZan.setImageResource(R.drawable.zan_focus);

        }
        zanFlag = !zanFlag;
        handler.removeMessages(DELAY_MESSAGE);
        handler.sendEmptyMessageDelayed(DELAY_MESSAGE,delayTime);
    }
複製程式碼

這裡我使用了handler來做延時的處理,每次點選時,先把handler的 DELAY_MESSAGE 先移除了,然後重新傳送延時 DELAY_MESSAGE 訊息,延時時間設定了500毫秒,如果在500毫秒內瘋狂點選,在handler訊息還未到達時,早已通過removeMessage將之前的訊息給移除掉了,通過這樣的一個小技巧,我們來看看效果:

點贊處理的一些小技巧

在我頻的繁操作下,也就是最後一次有效,這樣避免了之前頻繁的無效操作。

通過這個例子,開始延伸,想到了我們平時用到的搜尋,接下來講搜尋

實時搜尋網路請求

有的業務情況是在EditText中實時搜尋,顯示網路返回的結果,對於搜尋,一般都是給EditText新增TextWatcher監聽,在onTextChanged回撥中實時獲取當前EditText的內容,然後請求網路,這裡的問題也是和上面的問題一樣,因為在使用者輸入文字的時候,TextWatcher會實時回撥,回撥十分頻繁,我們只想在使用者確認搜尋結果時,使用者不在繼續輸入了,然後再去請求網路,這裡的處理也是和上面一樣,通過延時的方式來解決頻繁的操作。
虛擬碼

 editText.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
               
                handler.removeMessages(DELAY_MESSAGE);
                Message msg = handler.obtainMessage();
                msg.what = DELAY_MESSAGE;
                msg.obj = s.toString();
                handler.sendMessageDelayed(msg, delayTime);
            }

            @Override
            public void afterTextChanged(Editable s) {

            }
        });


    Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            //網路請求操作
            Log.e("TAG", "editText : " + msg.obj);
        }
    };
複製程式碼

效果如下,還是十分的nice的

點贊處理的一些小技巧


由於點贊部分,又讓我想起了點贊動畫的處理,這個地方參考了該篇博文的思路使用Glide V4 實現GIF點贊動畫 , 他的思路比較巧妙,也是我覺得特別喜歡的一個地方,下面我來說下思路:

1、通過view點選的位置,獲取view當前所在螢幕位置的座標

 int arr[] = new int[2];
 view.getLocationInWindow(arr);
複製程式碼

2、獲取Decorview,建立個一樣的view,add到Decorview上

        View decorView = getWindow().getDecorView();
        if (decorView instanceof FrameLayout) {
            frameLayout = (FrameLayout) decorView;
        }
        ImageView imageView = new ImageView(this);
        imageView.setImageResource(resInt);
        FrameLayout.LayoutParams layoutParams =
                new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT);
       
        //獲取位置拿到的座標是控制元件左上角的位置,採用margin的方式來定位控制元件在decorview中的位置
        layoutParams.leftMargin = arr[0];
        layoutParams.topMargin = arr[1];
        layoutParams.width = 100;
        layoutParams.height = 100;

        imageView.setLayoutParams(layoutParams);
        frameLayout.addView(imageView);
複製程式碼

3、將新增到Decorview的view做動畫,監聽動畫結束時移除該view

   set.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {}

            @Override
            public void onAnimationEnd(Animation animation) {
                ViewGroup parent = (ViewGroup) view.getParent();
                if (parent != null) {
                    parent.removeView(view);
                }
            }

            @Override
            public void onAnimationRepeat(Animation animation) {}
        });
複製程式碼

具體程式碼就不貼了,大家可以看原連結,下面貼一張我做的圖

點贊處理的一些小技巧

動畫主要就是一個透明+縮放的一個AnimationSet

相關文章