定時獲取來自服務器的消息

定時獲取來自服務器的消息

功能描述:

界面中有一個消息功能,點擊消息能夠查看消息列表。
定時向服務器發送請求接口獲取最新消息,並將消息數量以角標得形式顯示到消息功能上,
從而用戶能夠直觀得了解到接收了幾條消息。

思路

step 1:開一個服務,定時發送請求到服務器,獲取消息
    知識點:定時發送:observable.interval();
            網絡請求:okhttp;
            後臺運行:service;

step 2:獲得消息實體後,通知界面更新(activity或者fragment)

    
step 3:顯示消息數量的角標到對應控件
    知識點:badgeview;

實現

1,在後臺不停跑的service-MonitorService

public class MonitorService extends Service {
    public MonitorService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        return binder;
    }

    @Override
    public void onCreate() {
        LogUtil.d("onCreate");
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        LogUtil.d("onStartCommand");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        LogUtil.d("onDestroy");
        super.onDestroy();
    }

    private MonitorBinder binder = new MonitorBinder();
    public class MonitorBinder extends Binder{

        /**
         * 每隔幾秒向服務器發送請求,獲取最新消息數量
         * @param  intervalSecond 時間間隔,單位秒
         */
        public Observable<String> getNewMessage(int intervalSecond){
            // 默認5秒
            if (intervalSecond<1) intervalSecond = 5;
            return io.reactivex.Observable
                    .interval(intervalSecond, TimeUnit.SECONDS)
                    .flatMap(new Function<Long, ObservableSource<String>>() {
                        @Override
                        public ObservableSource<String> apply(Long aLong) throws Exception {
                            return io.reactivex.Observable                    .create(new ObservableOnSubscribe<String>() {
                                @Override
                                public void subscribe(final ObservableEmitter<String> emitter) throws Exception {
                                    LogUtil.e("------subscribe-------");
                                    MessageModel model = new MessageModel();
                                    model.loadData(  "", new MessageModel.OnMessageRequestListener() {
                                        @Override
                                        public void onFailed(IOException e) {
                                            emitter.onNext("");
                                        }

                                        @Override
                                        public void onSuccess(String json) {
                                            emitter.onNext(json);
                                        }
                                    });
                                }
                            });
                        }
                    });
        }

    }
}

2,網絡請求須要的Module

public class MessageModel {

    private static final OkHttpClient OK_HTTP_CLIENT = new OkHttpClient();

    public void loadData(String url, final OnMessageRequestListener listener){
        LogUtil.e(url);
        Request request = new Request.Builder()
                .url(url)
                .build();
        Call call = OK_HTTP_CLIENT.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                listener.onFailed(e);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                listener.onSuccess(response.body().string());
            }
        });

    }

    public interface OnMessageRequestListener{
        void onFailed(IOException e);
        void onSuccess(String json);
    }
}

3,設置角標的view

public class BadgeView extends TextView {
    private boolean mHideOnNull;

    public BadgeView(Context context) {
        this(context, (AttributeSet)null);
    }

    public BadgeView(Context context, AttributeSet attrs) {
        this(context, attrs, 16842884);
    }

    public BadgeView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        this.mHideOnNull = true;
        this.init();
    }

    private void init() {
        if (!(this.getLayoutParams() instanceof LayoutParams)) {
            LayoutParams layoutParams = new LayoutParams(-2, -2, 53);
            this.setLayoutParams(layoutParams);
        }

        this.setTextColor(-1);
        this.setTypeface(Typeface.DEFAULT_BOLD);
        this.setTextSize(2, 11.0F);
        this.setPadding(this.dip2Px(5.0F), this.dip2Px(1.0F), this.dip2Px(5.0F), this.dip2Px(1.0F));
        this.setBackground(9, Color.parseColor("#d3321b"));
        this.setGravity(17);
        this.setHideOnNull(true);
        this.setBadgeCount(0);
    }

    public void setBackground(int dipRadius, int badgeColor) {
        int radius = this.dip2Px((float)dipRadius);
        float[] radiusArray = new float[]{(float)radius, (float)radius, (float)radius, (float)radius, (float)radius, (float)radius, (float)radius, (float)radius};
        RoundRectShape roundRect = new RoundRectShape(radiusArray, (RectF)null, (float[])null);
        ShapeDrawable bgDrawable = new ShapeDrawable(roundRect);
        bgDrawable.getPaint().setColor(badgeColor);
        this.setBackgroundDrawable(bgDrawable);
    }

    public boolean isHideOnNull() {
        return this.mHideOnNull;
    }

    public void setHideOnNull(boolean hideOnNull) {
        this.mHideOnNull = hideOnNull;
        this.setText(this.getText());
    }

    public void setText(CharSequence text, BufferType type) {
        if (!this.isHideOnNull() || text != null && !text.toString().equalsIgnoreCase("0")) {
            this.setVisibility(0);
        } else {
            this.setVisibility(8);
        }

        super.setText(text, type);
    }

    public void setBadgeCount(int count) {
        this.setText(String.valueOf(count));
    }

    public Integer getBadgeCount() {
        if (this.getText() == null) {
            return null;
        } else {
            String text = this.getText().toString();

            try {
                return Integer.parseInt(text);
            } catch (NumberFormatException var3) {
                return null;
            }
        }
    }

    public void setBadgeGravity(int gravity) {
        LayoutParams params = (LayoutParams)this.getLayoutParams();
        params.gravity = gravity;
        this.setLayoutParams(params);
    }

    public int getBadgeGravity() {
        LayoutParams params = (LayoutParams)this.getLayoutParams();
        return params.gravity;
    }

    public void setBadgeMargin(int dipMargin) {
        this.setBadgeMargin(dipMargin, dipMargin, dipMargin, dipMargin);
    }

    public void setBadgeMargin(int leftDipMargin, int topDipMargin, int rightDipMargin, int bottomDipMargin) {
        LayoutParams params = (LayoutParams)this.getLayoutParams();
        params.leftMargin = this.dip2Px((float)leftDipMargin);
        params.topMargin = this.dip2Px((float)topDipMargin);
        params.rightMargin = this.dip2Px((float)rightDipMargin);
        params.bottomMargin = this.dip2Px((float)bottomDipMargin);
        this.setLayoutParams(params);
    }

    public int[] getBadgeMargin() {
        LayoutParams params = (LayoutParams)this.getLayoutParams();
        return new int[]{params.leftMargin, params.topMargin, params.rightMargin, params.bottomMargin};
    }

    public void incrementBadgeCount(int increment) {
        Integer count = this.getBadgeCount();
        if (count == null) {
            this.setBadgeCount(increment);
        } else {
            this.setBadgeCount(increment + count);
        }

    }

    public void decrementBadgeCount(int decrement) {
        this.incrementBadgeCount(-decrement);
    }

    public void setTargetView(TabWidget target, int tabIndex) {
        View tabView = target.getChildTabViewAt(tabIndex);
        this.setTargetView(tabView);
    }

    public void setTargetView(View target) {
        if (this.getParent() != null) {
            ((ViewGroup)this.getParent()).removeView(this);
        }

        if (target != null) {
            if (target.getParent() instanceof FrameLayout) {
                ((FrameLayout)target.getParent()).addView(this);
            } else if (target.getParent() instanceof ViewGroup) {
                ViewGroup parentContainer = (ViewGroup)target.getParent();
                int groupIndex = parentContainer.indexOfChild(target);
                parentContainer.removeView(target);
                FrameLayout badgeContainer = new FrameLayout(this.getContext());
                android.view.ViewGroup.LayoutParams parentlayoutParams = target.getLayoutParams();
                badgeContainer.setLayoutParams(parentlayoutParams);
                target.setLayoutParams(new android.view.ViewGroup.LayoutParams(-1, -1));
                parentContainer.addView(badgeContainer, groupIndex, parentlayoutParams);
                badgeContainer.addView(target);
                badgeContainer.addView(this);
            } else if (target.getParent() == null) {
                Log.e(this.getClass().getSimpleName(), "ParentView is needed");
            }

        }
    }

    private int dip2Px(float dip) {
        return (int)(dip * this.getContext().getResources().getDisplayMetrics().density + 0.5F);
    }
}

4,activity中實現

public class MainActivity extends AppCompatActivity {

   
    private MonitorService.MonitorBinder binder;
    private ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.e("test","------onServiceConnected-------");
            binder = (MonitorService.MonitorBinder) service;
            // 假設json 不爲空。爲:有消息。
            disposable = binder.getNewMessage(6)
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(json -> {
                        if (!TextUtils.isEmpty(json)) {
                            Log.e("test","------subscribe  success-------");
                            // 假設json 不爲空。爲:有消息。
                            View view = findViewById(R.id.tv_menu);
                            BadgeView badgeView = new BadgeView(MainActivity.this);
                            badgeView.setTargetView(view);
                            badgeView.setBadgeCount(1);
                        }
                    });
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initToolbar();
        bindService(new Intent(this,MonitorService.class),serviceConnection,BIND_AUTO_CREATE);
 

    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        if(disposable!=null&&!disposable.isDisposed()){
            disposable.dispose();
        }
        unbindService(serviceConnection);
    }

注意:

1,記得在androidManifest.xml中配置MonitorService服務
2,若是須要設置的目標view是button的話可能會不顯示,代碼中的tv_menu 是textview。
相關文章
相關標籤/搜索