Android開發中那些看似普通卻很麻煩的操作


安卓開發過程中,經常會出現一些比較麻煩的情況,並不是說難以解決,只是有時候的解決方法會讓代碼看起來像是玩具一般,生怕一不小心就crash掉,這裏列出一些常見的麻煩;


針對不同的情況可能這些方法不是萬能鑰匙,只是提供一些解決的想法

一、攜帶 label 的 text 文本

1、問題情景

很多時候,我們需要向用戶展示一些信息,比如這種情況:

這裏寫圖片描述

或者說是這種情況:

這裏寫圖片描述

可以看到,對於這種行式文本信息,一般來說前面是一個label,不會改變,後面緊跟結果值

2、通常方案

通常時候我們需要這樣來處理:

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <TextView
        style="@style/TextViewStandard"
        android:text="label:"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    <TextView
        style="@style/TextViewStandard"
        android:text="I'm value"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
</LinearLayout>

若是簡單的佈局還好,若是本來佈局就比較複雜,或者在使用了ConstraintLayout佈局的情況下,如此處理就會使得佈局臃腫,在進行measure、layout和draw過程中,會很影響性能。

3、使用 ColorTextDrawable 設定label

對於安卓原生的View來說,TextView的功能強大的令人髮指;
其中就包括了 drawable***(drawableRight等屬性)以及drawablePadding,如果可以將 label部分變成一個drawable,然後設置到textview的上下左右位置,那麼對於以上情景出現的文本信息,一個控件就足以解決。

在佈局裏面這樣(和普通方式沒區別):

<TextView
    android:id="@+id/tv_text"
    style="@style/TextViewStandard"
    android:text="I'm value"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"/>

然後在activity中這樣:

((TextView) findViewById(R.id.tv_text)).setCompoundDrawables(ColorTextDrawable.getTextDrawable(context, Color.RED,18),null,null,null);

對於那種左右上下都有label的界面,這種方法會方便很多,並且可以動態的去調整drawable中文字的大小顏色。

並且ColorTextDrawable類也很簡單,基本沒有什麼複雜的操作,這裏直接貼上源碼:

/**
 * Created on 2018/1/17
 * function : 文本形式的drawable
 */

public class ColorTextDrawable extends Drawable {
    private static final String TAG = "TextDrawable";

    private Context context;
    private TextPaint textPaint;
    private CharSequence charSequence;
    private int textSize;
    private Rect rect;
    private int alpha;
    private int color;
    private int xOffset;
    private int yOffset;

    private ColorTextDrawable(Context context) {
        this.context = context;
        textPaint = new TextPaint();
        textPaint.setAntiAlias(true);
        textPaint.setTextAlign(Paint.Align.LEFT);
        charSequence = "";
    }

    private ColorTextDrawable(Context context, int xOffset, int yOffset) {
        this(context);
        this.xOffset = xOffset;
        this.yOffset = yOffset;
    }

    /**
     * @param context  上下文
     * @param text     文本
     * @param color    顏色
     * @param textSize 字體大小
     * @return drawable資源
     */
    public static ColorTextDrawable getTextDrawable(Context context, String text, int color, int textSize) {
        ColorTextDrawable textDrawable = new ColorTextDrawable(context)
                .setText(text)
                .setColor(color)
                .setTextSize(textSize);
        textDrawable.setBounds(0, 0, textDrawable.getIntrinsicWidth(), textDrawable.getIntrinsicHeight());
        return textDrawable;
    }

    public static ColorTextDrawable getTextDrawable(Context context, String text, int color, int textSize, int xOffset, int yOffset) {
        ColorTextDrawable textDrawable = new ColorTextDrawable(context, xOffset, yOffset)
                .setText(text)
                .setColor(color)
                .setTextSize(textSize);
        textDrawable.setBounds(0, 0, textDrawable.getIntrinsicWidth() + Math.abs(xOffset), textDrawable.getIntrinsicHeight() + Math.abs(yOffset));
        return textDrawable;
    }

    @Override
    public void draw(Canvas canvas) {
        textPaint.setTextSize(textSize);
        canvas.drawText(charSequence, 0, charSequence.length(), xOffset, yOffset - textPaint.getFontMetrics().top, textPaint);
    }

    @Override
    public void setBounds(Rect bounds) {
        super.setBounds(bounds);
        this.rect = bounds;
    }

    @Override
    public void setBounds(int left, int top, int right, int bottom) {
        super.setBounds(left, top, right, bottom);
        this.rect = new Rect(left, top, right, bottom);
    }

    @Override
    public void setAlpha(int alpha) {
        this.alpha = alpha;
        textPaint.setAlpha(alpha);
    }

    @Override
    public void setColorFilter(@Nullable ColorFilter colorFilter) {
        textPaint.setColorFilter(colorFilter);
    }

    @Override
    public int getOpacity() {
        return PixelFormat.TRANSLUCENT;
    }

    @Override
    public int getIntrinsicWidth() {
        return (int) textPaint.measureText(charSequence.toString());
    }

    @Override
    public int getIntrinsicHeight() {
        return (int) (textPaint.getFontMetrics().bottom - textPaint.getFontMetrics().top);
    }

    @Override
    public int getMinimumWidth() {
        return getIntrinsicWidth();
    }

    @Override
    public int getMinimumHeight() {
        return getIntrinsicHeight();
    }

    public ColorTextDrawable setTextSize(int textSize) {
        this.textSize = textSize;
        textPaint.setTextSize(textSize);
        return this;
    }

    public CharSequence getText() {
        return this.charSequence;
    }

    public ColorTextDrawable setText(CharSequence charSequence) {
        this.charSequence = charSequence;
        return this;
    }

    public ColorTextDrawable setColor(int color) {
        this.color = color;
        textPaint.setColor(color);
        return this;
    }

    public int getxOffset() {
        return xOffset;
    }

    public void setxOffset(int xOffset) {
        this.xOffset = xOffset;
    }

    public int getyOffset() {
        return yOffset;
    }

    public void setyOffset(int yOffset) {
        this.yOffset = yOffset;
    }
}

其中對getTextDrawable進行一次重載,可以用來設定x和y方向的偏移量,偏移量爲正表示向右向下(安卓座標軸正方向);

4、使用LineMenuView

如果是一些攜帶了圖片的文本信息,那麼單純的使用 ColorTextDrawable 是無法完成需求的,這時候就需要使用複雜式菜單佈局——LineMenuView

這個控件可以完成以下功能:

這裏寫圖片描述

實際view樹並沒有減少層次,不過因爲多了一層封裝,至少佈局文件可以看起來簡單一些。

github地址:LineMenuView

二、AdapterView中item的寬度問題

1、問題情景

安卓開發中,列表視圖基本算是最複雜的一種,ListView,GridView,RecyclerView;

一般來說,對於一些記錄性的內容,都需要使用ListView或者RecyclerView進行滾動顯示,像以下這種情況:

這裏寫圖片描述

需要同時顯示三列信息,但是中間“領取時間”一列在我們搬運代碼時無法確定寬度,這樣標題的位置可能會錯位。

2、使用 weight 解決(LinearLayout)

LinearLayout提供了weight屬性,可以將總寬度n等分,這樣可以保證下面每個Item的寬度和表頭一樣。

想下面這樣,表頭佈局和Item佈局使用相同代碼

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        style="@style/TextViewStandard"
        android:layout_weight="1"
        android:gravity="center"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="獎勵類別"/>

    <TextView
        android:layout_weight="1"
        android:gravity="center"
        style="@style/TextViewStandard"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="領取時間"/>

    <TextView
        android:gravity="center"
        style="@style/TextViewStandard"
        android:layout_weight="1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="獎勵金額"/>
</LinearLayout>

這樣肯定可以保證寬度的統一,但如此依賴,不說weight值很難確定,同樣的Item無法根據自己真實數據的寬度來動態改變列的寬度。

3、玩具模式——使用GridView或者TableLayout

使用表格的形式,強行固定列寬;比如使用TableLayout來顯示數據,不過因爲該佈局沒有一般AdapterView的特性,很容易子佈局數量膨脹爆炸。

使用GridView的話。。。,需要自己添加數條數據,說起來還不如使用LiearLayout來的方便

4、列寬度監聽——使用 CallBackAfterItemMeasure回調

先把回調接口貼出來,然後說明有什麼用處:

/**
 * Created on 2018/3/6
 * function : 當容器類組件中item有佈局變化時,通知刷新佈局效果
 */

public interface CallBackAfterItemMeasure {
    /**
     * 標誌位
     */
    int TAG_ONE = 1;
    int TAG_TWO = 2;
    int TAG_THREE = 3;

    /**
     * @param tag           若是同時檢測多個寬高,則用於區分
     * @param measureWidth  item中想要獲取的view的寬度
     * @param measureHeight item中想要獲取的view的高度
     * @return true則表示此次已經完成了測量, 以後都不需要再調用該方法了;
     * false則表示每次刷新視圖都需要實現類執行該方法完成寬度和高度的設置
     */
    boolean doAfterItemMeasure(int tag, int measureWidth, int measureHeight);
}

看到該類一般可以明白個大概,就是在 item 加入AdapterView中時(填充數據後),主動請求表頭佈局來刷新自身的寬度,假設情景模式中的佈局是RecyclerView

Item對應的xml文件和表頭佈局文件使用相同的代碼:

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        android:id="@+id/tv_"
        style="@style/TextViewStandard"
        android:layout_weight="1"
        android:gravity="center"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="獎勵類別"/>

    <TextView
        android:id="@+id/tv_time"
        android:gravity="center"
        style="@style/TextViewStandard"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="領取時間"/>

    <TextView
        android:gravity="center"
        style="@style/TextViewStandard"
        android:layout_weight="1"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="獎勵金額"/>
</LinearLayout>

可以看到,中間列寬設定爲:wrap_content
兩側兩列設置weight平分

那麼在AdapteronBindViewHolder方法中就可以這麼搞:

/**
 * 是否禁止處理callback
 */
private volatile boolean forbid;

@Override
public void onBindViewHolder(TestAdapter.ViewHolder holder, int position) {
    //... 刷新佈局數據
    if(callback!=null&&!forbid) {
        postMeasure(holder.mTvTime,CallBackAfterItemMeasure.TAG_ONE);
    }
}

/**
 * 通知callback執行
 */
private void postMeasure(View view,int tag){
    view.post(() -> {
        if(forbid){
            return;
        }

        int measuredWidth = view.getMeasuredWidth();
        int measuredHeight =view.getMeasuredHeight();
        //只有寬度和高度爲有效值時,纔會進行調用
        if(measuredHeight>0&&measuredWidth>0&&callback.doAfterItemMeasure(tag,measuredWidth,measuredHeight)) {
            forbid=true;
        }
    });
}

其中callback是指實現了CallBackAfterItemMeasure接口的Activity類,這樣只要 id 爲tv_time的TextView寬度一可能有變化,就通知Activity去刷新表頭列的寬度:

public class TestActivity implements CallBackAfterItemMeasure{
    // ... 其他代碼

    /**
     * @param tag           若是同時檢測多個寬高,則用於區分
     * @param measureWidth  item中想要獲取的view的寬度
     * @param measureHeight item中想要獲取的view的高度
     * @return true 則表示此次已經完成了測量, 以後都不需要再調用該方法了
     * false 則表示每次刷新視圖都需要實現類執行該方法完成寬度和高度的設置
     */
    @Override
    public boolean doAfterItemMeasure(int tag, int measureWidth, int measureHeight) {
        if (tag == CallBackAfterItemMeasure.TAG_ONE && measureWidth > mTvLabelTime.getMeasuredWidth()) {
            mTvLabelTime.setWidth(measureWidth);
        }
        return false;
    }
}

邏輯也很簡單,保證 表頭中間列 的寬度和 Item中間列的寬度相同。
表頭兩邊的兩列因爲weight的關係,和Item中兩側的兩列寬度肯定是相同的。
這是一種思路,只要設置了寬度爲wrap_content,那麼可以同時來控制很多表頭列的寬度和Item佈局列寬度相同,從而達到顯示效果統一的目的。

注:當然應該看到的是,這裏選取id爲tv_time有取巧成分,因爲對於時間格式,它們的長度基本是相同的,每個item對應的時間列不會有什麼變化。當然之前也說了,有了這種“反饋機制”,只要認真考慮,總可以找到很好的監聽方案。

三、統一的Toast或Dialog

1、問題情景

安卓裏面有三種最常用的提示方法:Toast,SnackBar,Dialog(爲了安全起見,使用DialogFragment也是可以的)
當然還有一種重量級提示:Notification

現在暫時不考慮SnackBar和Notifacation,一個因爲是必須依賴於現有界面;一個則是太“量”,不方便使用。

在應用中,經常會出現那種上一個Toast還未消失,下一個Toast已經顯示的情況;
或者說如果多個界面中需要彈出Dialog,不能每個界面都寫代碼吧。

這時就可以這樣:

2、公用toast與dialog

RxBus.getInstance().toObservable(BaseEvent.class).observeOn(AndroidSchedulers.mainThread()).subscribe(baseEvent -> {
    switch (baseEvent.operateCode) {
        //彈出提示
        case Const.SHOW_TOAST: {
            singleSmallToast.setText(baseEvent.data.toString());
            singleSmallToast.show();
            break;
        }

        //顯示登錄超時
        case Const.SHOW_LOGIN_DIALOG: {
            //在當前棧頂不是登錄界面情況下,再去彈出登錄窗口
            if (!(topActivity instanceof LoginActivity)) {
                DoLoginDialog.getInstance(topActivity).show();
            }else{
                RxBus.getInstance().post(new BaseEvent(Const.SHOW_TOAST,"登錄失敗,請重新登錄"));
            }
            break;
        }
    }
});

RxBus框架,代碼簡單,基於RxAndroid,簡單好用;
singleSmallToast就是一個普通的toast。

代碼:

DoLoginDialog.getInstance(topActivity).show();

就是顯示一個登錄框而已。

至於topActivity則可以通過監聽activity聲明週期得到(Application類的方法):

registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
    // ... 其他代碼
    @Override
    public void onActivityResumed(Activity activity) {
        topActivity = activity;
    }
    // ... 其他代碼
});

這裏貼上RxBus的源碼:源碼地址

/**
 * 功能----RxBus處理數據總線
 */
public  class  RxBus {
    private static volatile RxBus defaultInstance;

    private final Subject<Object> bus;

    private static CompositeDisposable group;

    // PublishSubject只會把在訂閱發生的時間點之後來自原始Observable的數據發射給觀察者
    private RxBus() {
        bus =  PublishSubject.create().toSerialized();
    }

    // 單例RxBus
    public static RxBus getInstance() {
        if (defaultInstance == null) {
            synchronized (RxBus.class) {
                if (defaultInstance == null) {
                    defaultInstance = new RxBus();
                    group=new CompositeDisposable();
                }
            }
        }
        return defaultInstance ;
    }

    // 發送一個新的事件
    public void post (Object o) {
       bus.onNext(o);
    }

    // 根據傳遞的 eventType 類型返回特定類型(eventType)的 被觀察者
    public <T>  Observable<T> toObservable (Class<T> event) {
        return bus.ofType(event);
    }
}

四、正方形 or 長方形 View

1、問題情景

現在有這種要求:
給定一個圖片,需要顯示在ImageView中,且不論圖片是什麼大小形狀,都需要保證ImageView顯示的寬高比。

針對這個情況:

2、遵照設計的意願

我們都是按照UI給的設計圖來的,拿米尺量一量,像這樣:

<ImageView
    android:src="@drawable/placeholder"
    android:layout_width="200dp"
    android:layout_height="100dp"/>

完美!肯定不會變形,這種情況下,ImageView不管如何測量,不僅長寬比,連長寬都不會變。

基本滿足了需求,就是有點生硬,在不同設備上,顯示的會有些區別。
不過總的來說,至少是總不錯的解決方案。

3、使用ConstraintLayout的屬性

<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal">

    <ImageView
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:src="@drawable/placeholder"
        app:layout_constraintDimensionRatio="2:1"/>
</android.support.constraint.ConstraintLayout>

沒錯就是這個:

app:layout_constraintDimensionRatio="2:1"

可以用來設定寬高比例,這樣一來,圖片擁有了寬高的可變性,又保持了寬高比例,相當的完美。

只不過如果本來不打算使用ConstraintLayout的話,這樣做就會導致view樹層級加深,會稍微影響一下性能。

4、“欺騙”View的測量結果

最後一種就比較正規了,我們可以定義一種只能保持一種長寬比的ImageView,比如說:

RectImageView佈局(正方形,寬高1:1):

/**
 * Created on 2018/3/27
 * function : 寬高相同的ImageView
 */

public class RectImageView extends AppCompatImageView {
    public RectImageView(Context context) {
        super(context);
    }

    public RectImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public RectImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        //讓高度等於寬度
        if (getMeasuredWidth() > 0 && getMeasuredHeight() > 0) {
            setMeasuredDimension(getMeasuredWidth(), getMeasuredWidth());
        }
    }
}

什麼都不理,直接在測量結束之後修改測量結果,“欺騙”view的onMeasure流程。
這樣的話,xml中怎麼寫區別都不大,只要不爲0就行:

<com.test.view.RectImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/placeholder"/>

五、toolbar居中顯示

1、問題情景

這個問題由來已久,不過大多數都是因爲UI切圖只給了IOS的,最後安卓照着做,還得學着ios將標題居中。
這個就比較扯了,因爲Toolbar中固有邏輯只是將Title文本設置到左側,並且控件基於動態生成,具體可以看源碼:

Toolbar類setTitle方法:

/**
 * Set the title of this toolbar.
 *
 * <p>A title should be used as the anchor for a section of content. It should
 * describe or name the content being viewed.</p>
 *
 * @param title Title to set
 */
public void setTitle(CharSequence title) {
    if (!TextUtils.isEmpty(title)) {
        if (mTitleTextView == null) {
            final Context context = getContext();
            mTitleTextView = new AppCompatTextView(context);
            mTitleTextView.setSingleLine();
            mTitleTextView.setEllipsize(TextUtils.TruncateAt.END);
            if (mTitleTextAppearance != 0) {
                mTitleTextView.setTextAppearance(context, mTitleTextAppearance);
            }
            if (mTitleTextColor != 0) {
                mTitleTextView.setTextColor(mTitleTextColor);
            }
        }
        if (!isChildOrHidden(mTitleTextView)) {
            addSystemView(mTitleTextView, true);
        }
    } else if (mTitleTextView != null && isChildOrHidden(mTitleTextView)) {
        removeView(mTitleTextView);
        mHiddenViews.remove(mTitleTextView);
    }
    if (mTitleTextView != null) {
        mTitleTextView.setText(title);
    }
    mTitleText = title;
}

要修改這個,只能說麻煩,根本沒有提供外部修改標題Gravity方法。

2、在toolbar中嵌套Textview

這個也是網上說的最多的一種方法,也就是自己搞一個TextView出來,同時設置AndroidManifest中Activity的label爲空字符串,讓系統標題無法顯示;

並且代碼中不能調用:

Activity.setTitle()

方法。

每次修改標題時,自己設置自定義的TextView內容。。。

詳情可以參考:其他博客

3、自定義Toolbar

好吧說到底其實上面方法可以很完美的解決居中問題,自定義Toolbar也和之前內容沒有多大區別,基本就是這樣子:

在xml中這樣使用:

<com.test.view.TitleCenterToolbar
    android:transitionName="toolbar"
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="?attr/colorPrimary"
    android:minHeight="?attr/actionBarSize"
    app:navigationIcon="@drawable/icon_back"
    android:theme="@style/ToolbarTheme"/>

CenterToolbar基本和原來一樣:

public class TitleCenterToolbar extends Toolbar {

    @BindView(R.id.tv_title)
    TextView mTvTitle;

    public TitleCenterToolbar(Context context) {
        this(context, null);
    }

    public TitleCenterToolbar(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, android.support.v7.appcompat.R.attr.toolbarStyle);
    }

    public TitleCenterToolbar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        initView();
    }

    /**
     * 初始化數據
     */
    private void initView() {
        inflate(getContext(), R.layout.layout_title_center_toolbar, this);
        ButterKnife.bind(this);
    }

    @Override
    public CharSequence getTitle() {
        return TextUtils.isEmpty(mTvTitle.getText())?null:mTvTitle.getText();
    }

    @Override
    public void setTitle(int resId) {
        mTvTitle.setText(resId);
    }

    @Override
    public void setTitle(CharSequence title) {
        mTvTitle.setText(title);
    }

    @Override
    public void setTitleTextAppearance(Context context, int resId) {
        mTvTitle.setTextAppearance(context, resId);
    }

    @Override
    public void setTitleTextColor(int color) {
        mTvTitle.setTextColor(color);
    }
}

layout_title_center_toolbar其實就是一個TextView:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.AppCompatTextView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/tv_title"
    style="@style/Base.TextAppearance.Widget.AppCompat.Toolbar.Title"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    android:paddingStart="@dimen/view_padding_margin_8dp"
    android:paddingEnd="@dimen/view_padding_margin_8dp"
    android:layout_gravity="center"
    android:ellipsize="marquee"
    android:marqueeRepeatLimit="marquee_forever"
    android:singleLine="true"
    tools:text="標題"/>

很簡單,只是修改了setTitle方法固有的邏輯,不會調用super,系統自然不會自動成功Title對應的TextView

然後如果每次需要修改標題的話,直接使用

Activity.setTitle()

就可以了。

注:
如果在代碼中調用了:

Activity. setSupportActionBar(toolbar);

那麼就儘量不要自己調用toolbar.setTitle方法,因爲無法保證自己對Toolbar的setTitle方法調用和系統自動對Toolbar的setTitle方法調用誰先執行。

六、目標跳轉

1、問題情景

這個不需要過多說明,安卓中太多的界面跳轉,如果只是手搓代碼來執行,那麼即便不覺得繁瑣;
也會因爲跳轉邏輯的複雜導致代碼混亂不堪。

還有,考慮一個問題1:


假設目前有界面A,需要跳轉到界面B,但界面B必須經過用戶實名身份認證之後才能進入,如果沒有實名認證,那麼只能跳轉到C,而界面C也需要用戶登錄成功後才能進入,否則就需要先跳轉到登錄界面D。

這怎麼辦?當然,可以在A界面就判斷是否登錄,是否進行了實名認證等等,然後分別跳轉到不同界面。
唔。。。,這個確實比較麻煩,如果界面足夠多,光是其中的邏輯就得炸掉。

在考慮一個問題2:


軟件開發時分了多個模塊,比如有X和Y;X中有活動A需要向Y模塊中的活動B跳轉,可惜的是,X模塊開發者只知道活動B名字,但需要傳什麼值就懵了,如果此時有模塊Z,同時有活動C需要向活動B跳轉,且跳轉時可能攜帶不同參數。。。

可以想象,Y模塊的開發者在編寫活動B時是多麼痛苦,需要同時兼顧多人的使用。

2、權限攔截與參數綁定——ARouter

又是一個框架,先看一下對於跳轉參數的處理:

/**
 * 非必須字段,可以爲null,表示使用關鍵字進行搜索過濾
 */
@Autowired(name = KEY_FILTER_SOURCE, required = false)
List<String> source;

就這樣,一個參數,一個解釋說明,說明什麼情況下需要傳遞,required表示是否必須name則說明KEY值

注:這裏需要說明,required字段設置爲true或者false對程序執行不會有影響,即便required爲true的字段沒有傳入,ARouter框架也是不會自動讓其Crash掉的

然後再說明一下ARouter對於權限的攔截處理;

相對於之前所說的“笨方法”——在當前界面判斷所有的權限來進行跳轉;
Arouter取了個巧,讓目標界面自己聲明自己所需的權限.
比如上面的問題1:讓B界面字節聲明自己需要實名認證權限,如果不滿足,在攔截器中進行降級,主動前往C界面,同樣的在C界面聲明瞭登錄權限,在攔截器中也做出了處理:如果未登錄,降級跳轉到登錄界面。

如此依賴,界面A中只要發出自己想要向C界面跳轉的請求,能不能成功,就不需要自己來處理了。

具體介紹見:路由攔截模塊——ARouter

持續更新中。。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章