scheme handler.

This commit is contained in:
cgspine
2020-05-16 21:10:35 +08:00
parent 56881a8e09
commit fafa06580e
10 changed files with 136 additions and 43 deletions
@@ -32,6 +32,7 @@ import com.qmuiteam.qmui.QMUIConfig;
import com.qmuiteam.qmui.arch.annotation.LatestVisitRecord;
import com.qmuiteam.qmui.arch.record.LatestVisitArgumentCollector;
import com.qmuiteam.qmui.arch.record.RecordArgumentEditor;
import com.qmuiteam.qmui.arch.scheme.QMUISchemeHandler;
import com.qmuiteam.qmui.skin.QMUISkinLayoutInflaterFactory;
import com.qmuiteam.qmui.skin.QMUISkinManager;
@@ -159,6 +160,10 @@ class InnerBaseActivity extends AppCompatActivity implements LatestVisitArgument
}
}
public final boolean isStartedByScheme() {
return getIntent().getBooleanExtra(QMUISchemeHandler.ARG_FROM_SCHEME, false);
}
protected boolean useQMUISkinLayoutInflaterFactory() {
return true;
}
@@ -61,6 +61,7 @@ import com.qmuiteam.qmui.arch.effect.QMUIFragmentEffectRegistry;
import com.qmuiteam.qmui.arch.effect.QMUIFragmentResultEffectHandler;
import com.qmuiteam.qmui.arch.record.LatestVisitArgumentCollector;
import com.qmuiteam.qmui.arch.record.RecordArgumentEditor;
import com.qmuiteam.qmui.arch.scheme.QMUISchemeHandler;
import com.qmuiteam.qmui.util.QMUIDisplayHelper;
import com.qmuiteam.qmui.util.QMUIKeyboardHelper;
import com.qmuiteam.qmui.util.QMUIViewHelper;
@@ -1362,6 +1363,13 @@ public abstract class QMUIFragment extends Fragment implements
return true;
}
public final boolean isStartedByScheme(){
Bundle arguments = getArguments();
return arguments != null && arguments.getBoolean(QMUISchemeHandler.ARG_FROM_SCHEME, false);
}
/**
* Fragment Transition Controller
*/
@@ -33,7 +33,7 @@ class ActivitySchemeItem extends SchemeItem {
@NonNull
private final Class<? extends Activity> mActivityClass;
@NonNull
@Nullable
private final Class<? extends QMUISchemeIntentFactory> mIntentFactoryCls;
public ActivitySchemeItem(@NonNull Class<? extends Activity> activityClass,
@@ -46,31 +46,33 @@ class ActivitySchemeItem extends SchemeItem {
@Nullable String[] keysForDouble) {
super(required, keysForInt, keysForBool, keysForLong, keysForFloat, keysForDouble);
mActivityClass = activityClass;
if (intentFactoryCls == null) {
mIntentFactoryCls = QMUIDefaultSchemeIntentFactory.class;
} else {
mIntentFactoryCls = intentFactoryCls;
}
mIntentFactoryCls = intentFactoryCls;
}
@Override
public boolean handle(@NonNull Activity activity, @NonNull Map<String, SchemeValue> scheme) {
public boolean handle(@NonNull QMUISchemeHandler handler,
@NonNull Activity activity,
@Nullable Map<String, SchemeValue> scheme) {
if (sFactories == null) {
sFactories = new HashMap<>();
}
QMUISchemeIntentFactory factory = sFactories.get(mIntentFactoryCls);
Class<? extends QMUISchemeIntentFactory> factoryCls = mIntentFactoryCls;
if(factoryCls == null){
factoryCls = handler.getDefaultIntentFactory();
}
QMUISchemeIntentFactory factory = sFactories.get(factoryCls);
if (factory == null) {
try {
factory = mIntentFactoryCls.newInstance();
sFactories.put(mIntentFactoryCls, factory);
factory = factoryCls.newInstance();
sFactories.put(factoryCls, factory);
} catch (Exception e) {
QMUILog.printErrStackTrace(QMUISchemeHandler.TAG, e,
"error to instance QMUISchemeIntentFactory: %d", mIntentFactoryCls.getSimpleName());
"error to instance QMUISchemeIntentFactory: %d", factoryCls.getSimpleName());
}
}
if (factory != null) {
if (factory.shouldBlockJump(activity, mActivityClass, scheme)) {
return true;
}
@@ -37,7 +37,7 @@ class FragmentSchemeItem extends SchemeItem {
private final Class<? extends QMUIFragmentActivity>[] mActivityClsList;
private final boolean mForceNewActivity;
private final String mForceNewActivityKey;
@NonNull
@Nullable
private final Class<? extends QMUISchemeFragmentFactory> mFragmentFactoryCls;
public FragmentSchemeItem(@NonNull Class<? extends QMUIFragment> fragmentCls,
@@ -56,15 +56,13 @@ class FragmentSchemeItem extends SchemeItem {
mActivityClsList = activityClsList;
mForceNewActivity = forceNewActivity;
mForceNewActivityKey = forceNewActivityKey;
if(fragmentFactoryCls == null){
mFragmentFactoryCls = QMUIDefaultSchemeFragmentFactory.class;
}else{
mFragmentFactoryCls = fragmentFactoryCls;
}
mFragmentFactoryCls = fragmentFactoryCls;
}
@Override
public boolean handle(@NonNull Activity activity, @Nullable Map<String, SchemeValue> scheme) {
public boolean handle(@NonNull QMUISchemeHandler handler,
@NonNull Activity activity,
@Nullable Map<String, SchemeValue> scheme) {
if (mActivityClsList.length == 0) {
QMUILog.d(QMUISchemeHandler.TAG, "Can not start a new fragment because the host is't provided");
return false;
@@ -72,21 +70,27 @@ class FragmentSchemeItem extends SchemeItem {
if (sFactories == null) {
sFactories = new HashMap<>();
}
QMUISchemeFragmentFactory factory = sFactories.get(mFragmentFactoryCls);
Class<? extends QMUISchemeFragmentFactory> factoryCls = mFragmentFactoryCls;
if (factoryCls == null) {
factoryCls = handler.getDefaultFragmentFactory();
}
QMUISchemeFragmentFactory factory = sFactories.get(factoryCls);
if (factory == null) {
try {
factory = mFragmentFactoryCls.newInstance();
sFactories.put(mFragmentFactoryCls, factory);
factory = factoryCls.newInstance();
sFactories.put(factoryCls, factory);
} catch (Exception e) {
QMUILog.printErrStackTrace(QMUISchemeHandler.TAG, e,
"error to instance QMUISchemeFragmentFactory: %d", mFragmentFactoryCls.getSimpleName());
"error to instance QMUISchemeFragmentFactory: %d", factoryCls.getSimpleName());
}
}
if (factory == null) {
return false;
}
if(factory.shouldBlockJump(activity, mFragmentCls, scheme)){
if (factory.shouldBlockJump(activity, mFragmentCls, scheme)) {
return true;
}
@@ -18,8 +18,15 @@ package com.qmuiteam.qmui.arch.scheme;
import android.app.Activity;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.util.Map;
public interface QMUISchemeHandleInterpolator {
boolean intercept(Activity activity, String action, Map<String, String> params, String origin);
boolean intercept(@NonNull QMUISchemeHandler schemeHandler,
@NonNull Activity activity,
@NonNull String action,
@Nullable Map<String, String> params,
@NonNull String origin);
}
@@ -64,10 +64,12 @@ public class QMUISchemeHandler {
}
}
private final String mPrefix;
private final List<QMUISchemeHandleInterpolator> mInterpolatorList;
private final long mBlockSameSchemeTimeout;
private final Class<? extends QMUISchemeIntentFactory> mDefaultIntentFactory;
private final Class<? extends QMUISchemeFragmentFactory> mDefaultFragmentFactory;
private String mLastHandledScheme = null;
private long mLastSchemeHandledTime = 0;
@@ -80,6 +82,26 @@ public class QMUISchemeHandler {
mInterpolatorList = null;
}
mBlockSameSchemeTimeout = builder.mBlockSameSchemeTimeout;
mDefaultIntentFactory = builder.mDefaultIntentFactory;
mDefaultFragmentFactory = builder.mDefaultFragmentFactory;
}
public String getPrefix() {
return mPrefix;
}
public Class<? extends QMUISchemeFragmentFactory> getDefaultFragmentFactory() {
return mDefaultFragmentFactory;
}
public Class<? extends QMUISchemeIntentFactory> getDefaultIntentFactory() {
return mDefaultIntentFactory;
}
@Nullable
public SchemeItem getSchemeItem(String action, Map<String, String> params){
return sSchemeMap.findScheme(action, params);
}
public boolean handle(String scheme){
@@ -116,7 +138,7 @@ public class QMUISchemeHandler {
boolean handled = false;
if(mInterpolatorList != null && !mInterpolatorList.isEmpty()){
for(QMUISchemeHandleInterpolator interpolator: mInterpolatorList){
if(interpolator.intercept(currentActivity, action, params, scheme)){
if(interpolator.intercept(this, currentActivity, action, params, scheme)){
handled = true;
break;
}
@@ -126,7 +148,7 @@ public class QMUISchemeHandler {
if(!handled){
SchemeItem schemeItem = sSchemeMap.findScheme(action, params);
if(schemeItem != null){
handled = schemeItem.handle(currentActivity, schemeItem.convertFrom(params));
handled = schemeItem.handle(this, currentActivity, schemeItem.convertFrom(params));
}
}
@@ -177,6 +199,8 @@ public class QMUISchemeHandler {
private String mPrefix;
private List<QMUISchemeHandleInterpolator> mInterpolatorList;
private long mBlockSameSchemeTimeout = BLOCK_SAME_SCHEME_DEFAULT_TIMEOUT;
private Class<? extends QMUISchemeIntentFactory> mDefaultIntentFactory = QMUIDefaultSchemeIntentFactory.class;
private Class<? extends QMUISchemeFragmentFactory> mDefaultFragmentFactory = QMUIDefaultSchemeFragmentFactory.class;
public Builder(@NonNull String prefix) {
mPrefix = prefix;
@@ -190,11 +214,21 @@ public class QMUISchemeHandler {
return this;
}
public Builder setBlockSameSchemeTimeout(long blockSameSchemeTimeout) {
public Builder blockSameSchemeTimeout(long blockSameSchemeTimeout) {
mBlockSameSchemeTimeout = blockSameSchemeTimeout;
return this;
}
public Builder defaultFragmentFactory(Class<? extends QMUISchemeFragmentFactory> defaultFragmentFactory) {
mDefaultFragmentFactory = defaultFragmentFactory;
return this;
}
public Builder defaultIntentFactory(Class<? extends QMUISchemeIntentFactory> defaultIntentFactory) {
mDefaultIntentFactory = defaultIntentFactory;
return this;
}
public QMUISchemeHandler build() {
return new QMUISchemeHandler(this);
}
@@ -19,12 +19,19 @@ package com.qmuiteam.qmui.arch.scheme;
import android.app.Activity;
import android.net.Uri;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.util.Map;
public class QMUISchemeParamValueDecoder implements QMUISchemeHandleInterpolator {
@Override
public boolean intercept(Activity activity, String action, Map<String, String> params, String origin) {
public boolean intercept(@NonNull QMUISchemeHandler schemeHandler,
@NonNull Activity activity,
@NonNull String action,
@Nullable Map<String, String> params,
@NonNull String origin) {
if (params != null) {
for (String key : params.keySet()) {
String oldValue = params.get(key);
@@ -61,15 +61,18 @@ public final class QMUIViewOffsetHelper {
}
public void onViewLayout() {
// Now grab the intended top
mLayoutTop = mView.getTop();
mLayoutLeft = mView.getLeft();
// And offset it as needed
updateOffsets();
onViewLayout(true);
}
private void updateOffsets() {
public void onViewLayout(boolean applyOffset) {
mLayoutTop = mView.getTop();
mLayoutLeft = mView.getLeft();
if(applyOffset){
applyOffsets();
}
}
public void applyOffsets() {
ViewCompat.offsetTopAndBottom(mView, mOffsetTop - (mView.getTop() - mLayoutTop));
ViewCompat.offsetLeftAndRight(mView, mOffsetLeft - (mView.getLeft() - mLayoutLeft));
}
@@ -83,7 +86,7 @@ public final class QMUIViewOffsetHelper {
public boolean setTopAndBottomOffset(int offset) {
if (mVerticalOffsetEnabled && mOffsetTop != offset) {
mOffsetTop = offset;
updateOffsets();
applyOffsets();
return true;
}
return false;
@@ -98,7 +101,7 @@ public final class QMUIViewOffsetHelper {
public boolean setLeftAndRightOffset(int offset) {
if (mHorizontalOffsetEnabled && mOffsetLeft != offset) {
mOffsetLeft = offset;
updateOffsets();
applyOffsets();
return true;
}
return false;
@@ -111,7 +114,7 @@ public final class QMUIViewOffsetHelper {
if (mOffsetLeft != leftOffset || mOffsetTop != topOffset) {
mOffsetLeft = leftOffset;
mOffsetTop = topOffset;
updateOffsets();
applyOffsets();
return true;
}
return false;
@@ -60,7 +60,7 @@ import butterknife.ButterKnife;
@FragmentScheme(
name = "tab",
activities = {QDMainActivity.class},
required = {"mode=2"},
required = {"mode=2", "name"},
keysWithIntValue = {"mode"})
public class QDTabSegmentScrollableModeFragment extends BaseFragment {
@SuppressWarnings("FieldCanBeLocal") private final int TAB_COUNT = 10;
@@ -115,6 +115,22 @@ public class QDTabSegmentScrollableModeFragment extends BaseFragment {
}
};
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(isStartedByScheme()){
Toast.makeText(getContext(), "started by scheme", Toast.LENGTH_SHORT).show();
Bundle args = getArguments();
if(args != null){
int mode = args.getInt("mode");
Toast.makeText(getContext(), "mode = " + mode, Toast.LENGTH_SHORT).show();
}
}
}
@Override
protected View onCreateView() {
View rootView = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_tab_viewpager_layout, null);
@@ -20,6 +20,9 @@ import android.app.Activity;
import android.util.Log;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.qmuiteam.qmui.arch.QMUISwipeBackActivityManager;
import com.qmuiteam.qmui.arch.scheme.QMUISchemeHandleInterpolator;
import com.qmuiteam.qmui.arch.scheme.QMUISchemeHandler;
@@ -43,10 +46,14 @@ public class QDSchemeManager {
private QDSchemeManager() {
mSchemeHandler = new QMUISchemeHandler.Builder(SCHEME_PREFIX)
.setBlockSameSchemeTimeout(1000)
.blockSameSchemeTimeout(1000)
.addInterpolator(new QMUISchemeHandleInterpolator() {
@Override
public boolean intercept(Activity activity, String action, Map<String, String> params, String origin) {
public boolean intercept(@NonNull QMUISchemeHandler schemeHandler,
@NonNull Activity activity,
@NonNull String action,
@Nullable Map<String, String> params,
@NonNull String origin) {
// Log the scheme.
Log.i(TAG, "handle scheme: " + origin);
return false;