Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 92ae43d5 authored by Steve McKay's avatar Steve McKay
Browse files

Move Injector impl into separate class.

Change-Id: I070114479755571e93b9256e0cbf35780b962033
parent 04718263
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import com.android.documentsui.base.DocumentInfo;
import com.android.documentsui.base.DocumentStack;
import com.android.documentsui.base.RootInfo;
import com.android.documentsui.dirlist.DocumentDetails;
import com.android.documentsui.dirlist.Model;

public interface ActionHandler {

@@ -82,4 +83,10 @@ public interface ActionHandler {
     * app.
     */
    void initLocation(Intent intent);

    /**
     * Allow action handler to be initialized in a new scope.
     * @return
     */
    <T extends ActionHandler> T reset(Model model, boolean searchMode);
}
+19 −25
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ import android.view.MenuItem;
import android.view.View;

import com.android.documentsui.AbstractActionHandler.CommonAddons;
import com.android.documentsui.Injector.Injected;
import com.android.documentsui.NavigationViewManager.Breadcrumb;
import com.android.documentsui.base.DocumentInfo;
import com.android.documentsui.base.LocalPreferences;
@@ -60,39 +61,38 @@ import com.android.documentsui.selection.Selection;
import com.android.documentsui.sidebar.RootsFragment;
import com.android.documentsui.sorting.SortController;
import com.android.documentsui.sorting.SortModel;
import com.android.documentsui.ui.MessageBuilder;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.Executor;

public abstract class BaseActivity<T extends ActionHandler>
        extends Activity
        implements CommonAddons, Injector, NavigationViewManager.Environment {
public abstract class BaseActivity
        extends Activity implements CommonAddons, NavigationViewManager.Environment {

    private static final String BENCHMARK_TESTING_PACKAGE = "com.android.documentsui.appperftests";

    protected SearchViewManager mSearchManager;
    protected State mState;

    @Injected
    protected Injector<?> mInjector;

    protected @Nullable RetainedState mRetainedState;
    protected RootsCache mRoots;
    protected DocumentsAccess mDocs;
    protected MessageBuilder mMessages;
    protected DrawerController mDrawer;

    protected NavigationViewManager mNavigator;
    protected SortController mSortController;

    protected T mActions;

    private final List<EventListener> mEventListeners = new ArrayList<>();
    private final String mTag;

    @LayoutRes
    private int mLayoutId;

    private RootsMonitor<BaseActivity<?>> mRootsMonitor;
    private RootsMonitor<BaseActivity> mRootsMonitor;

    private long mStartTime;

@@ -107,13 +107,7 @@ public abstract class BaseActivity<T extends ActionHandler>
    protected abstract void includeState(State initialState);
    protected abstract void onDirectoryCreated(DocumentInfo doc);

    // Get ref to to focus manager without reset. Presumes it has had scrope vars initialized.
    protected abstract FocusManager getFocusManager();

    public final MessageBuilder getMessages() {
        assert(mMessages != null);
        return mMessages;
    }
    public abstract Injector<?> getInjector();

    @CallSuper
    @Override
@@ -129,8 +123,9 @@ public abstract class BaseActivity<T extends ActionHandler>

        setContentView(mLayoutId);

        mInjector = getInjector();
        mState = getState(icicle);
        mDrawer = DrawerController.create(this, getActivityConfig());
        mDrawer = DrawerController.create(this, mInjector.config);
        Metrics.logActivityLaunch(this, mState, intent);

        // we're really interested in retainining state in our very complex
@@ -139,7 +134,6 @@ public abstract class BaseActivity<T extends ActionHandler>
        mRetainedState = (RetainedState) getLastNonConfigurationInstance();
        mRoots = DocumentsApplication.getRootsCache(this);
        mDocs = DocumentsAccess.create(this);
        mMessages = new MessageBuilder(this);

        DocumentsToolbar toolbar = (DocumentsToolbar) findViewById(R.id.toolbar);
        setActionBar(toolbar);
@@ -186,7 +180,7 @@ public abstract class BaseActivity<T extends ActionHandler>

        mRootsMonitor = new RootsMonitor<>(
                this,
                mActions,
                mInjector.actions,
                mRoots,
                mDocs,
                mState,
@@ -238,8 +232,8 @@ public abstract class BaseActivity<T extends ActionHandler>

        includeState(state);

        state.showAdvanced =
                Shared.mustShowDeviceRoot(intent) || getScopedPreferences().getShowDeviceRoot();
        state.showAdvanced = Shared.mustShowDeviceRoot(intent)
                || mInjector.prefs.getShowDeviceRoot();

        // Only show the toggle if advanced isn't forced enabled.
        state.showDeviceStorageOption = !Shared.mustShowDeviceRoot(intent);
@@ -285,7 +279,7 @@ public abstract class BaseActivity<T extends ActionHandler>
            new GetRootDocumentTask(
                    root,
                    this,
                    mActions::openContainerDocument)
                    mInjector.actions::openContainerDocument)
                    .executeOnExecutor(getExecutorForCurrentDirectory());
        }
    }
@@ -417,8 +411,8 @@ public abstract class BaseActivity<T extends ActionHandler>
        return (root.flags & Root.FLAG_SUPPORTS_SEARCH) != 0;
    }

    public static BaseActivity<?> get(Fragment fragment) {
        return (BaseActivity<?>) fragment.getActivity();
    public static BaseActivity get(Fragment fragment) {
        return (BaseActivity) fragment.getActivity();
    }

    public State getDisplayState() {
@@ -437,7 +431,7 @@ public abstract class BaseActivity<T extends ActionHandler>
        Metrics.logUserAction(this,
                display ? Metrics.USER_ACTION_SHOW_ADVANCED : Metrics.USER_ACTION_HIDE_ADVANCED);

        getScopedPreferences().setShowDeviceRoot(display);
        mInjector.prefs.setShowDeviceRoot(display);
        mState.showAdvanced = display;
        RootsFragment.get(getFragmentManager()).onDisplayStateChanged();
        invalidateOptionsMenu();
@@ -590,7 +584,7 @@ public abstract class BaseActivity<T extends ActionHandler>
        return false;
    }

    protected boolean focusRoots() {
    protected boolean focusSidebar() {
        RootsFragment rf = RootsFragment.get(getFragmentManager());
        assert (rf != null);
        return rf.requestFocus();
+6 −10
Original line number Diff line number Diff line
@@ -54,7 +54,6 @@ import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

/** A class that handles navigation and focus within the DirectoryFragment. */
public final class FocusManager implements FocusHandler {
    private static final String TAG = "FocusManager";

@@ -82,16 +81,16 @@ public final class FocusManager implements FocusHandler {

    @Override
    public boolean advanceFocusArea() {
        boolean toogleHappened = false;
        boolean focusChanged = false;
        if (mNavDrawerHasFocus) {
            mDrawer.setOpen(false);
            focusDirectoryList();
        } else {
            mDrawer.setOpen(true);
            toogleHappened = mRootsFocuser.run();
            focusChanged = mRootsFocuser.run();
        }

        if (toogleHappened) {
        if (focusChanged) {
            mNavDrawerHasFocus = !mNavDrawerHasFocus;
            return true;
        }
@@ -131,8 +130,7 @@ public final class FocusManager implements FocusHandler {
    @Override
    public boolean focusDirectoryList() {
        if (mScope.adapter.getItemCount() == 0) {
            if (DEBUG)
                Log.v(TAG, "Nothing to focus.");
            if (DEBUG) Log.v(TAG, "Nothing to focus.");
            return false;
        }

@@ -141,8 +139,7 @@ public final class FocusManager implements FocusHandler {
        // vs. Cut focused
        // item)
        if (mSelectionMgr.hasSelection()) {
            if (DEBUG)
                Log.v(TAG, "Existing selection found. No focus will be done.");
            if (DEBUG) Log.v(TAG, "Existing selection found. No focus will be done.");
            return false;
        }

@@ -341,8 +338,7 @@ public final class FocusManager implements FocusHandler {
     * @param pos
     * @param callback A callback to call after the given item has been focused.
     */
    private void focusItem(final int pos, @Nullable
    final FocusCallback callback) {
    private void focusItem(final int pos, @Nullable final FocusCallback callback) {
        if (mScope.pendingFocusId != null) {
            Log.v(TAG, "clearing pending focus id: " + mScope.pendingFocusId);
            mScope.pendingFocusId = null;
+87 −11
Original line number Diff line number Diff line
@@ -15,6 +15,9 @@
 */
package com.android.documentsui;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.SOURCE;

import android.support.annotation.Nullable;
import android.support.v7.widget.RecyclerView;
import android.view.MenuItem;
@@ -28,19 +31,92 @@ import com.android.documentsui.dirlist.Model;
import com.android.documentsui.selection.SelectionManager;
import com.android.documentsui.selection.SelectionManager.SelectionPredicate;
import com.android.documentsui.ui.DialogController;
import com.android.documentsui.ui.MessageBuilder;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

/**
 * Provides access to runtime dependencies.
 */
public interface Injector {

    ActivityConfig getActivityConfig();
    ScopedPreferences getScopedPreferences();
    SelectionManager getSelectionManager(DocumentsAdapter adapter, SelectionPredicate canSetState);
    MenuManager getMenuManager();
    DialogController getDialogController();
    ActionHandler getActionHandler(@Nullable Model model, boolean searchMode);
    ActionModeController getActionModeController(
            SelectionDetails selectionDetails, EventHandler<MenuItem> menuItemClicker, View view);
    FocusManager getFocusManager(RecyclerView view, Model model);
public class Injector<T extends ActionHandler> {

    public final ActivityConfig config;
    public final ScopedPreferences prefs;
    public final MessageBuilder messages;

    public MenuManager menuManager;
    public DialogController dialogs;

    @ContentScoped
    public ActionModeController actionModeController;

    @ContentScoped
    public T actions;

    @ContentScoped
    public FocusManager focusManager;

    @ContentScoped
    public SelectionManager selectionMgr;

    // must be initialized before calling super.onCreate because prefs
    // are used in State initialization.
    public Injector(
            ActivityConfig config,
            ScopedPreferences prefs,
            MessageBuilder messages,
            DialogController dialogs) {

        this.config = config;
        this.prefs = prefs;
        this.messages = messages;
        this.dialogs = dialogs;
    }

    public FocusManager getFocusManager(RecyclerView view, Model model) {
        assert (focusManager != null);
        return focusManager.reset(view, model);
    }

    public SelectionManager getSelectionManager(
            DocumentsAdapter adapter, SelectionPredicate canSetState) {
        return selectionMgr.reset(adapter, canSetState);
    }

    public final ActionModeController getActionModeController(
            SelectionDetails selectionDetails, EventHandler<MenuItem> menuItemClicker, View view) {
        return actionModeController.reset(selectionDetails, menuItemClicker, view);
    }

    public T getActionHandler(
            @Nullable Model model, boolean searchMode) {

        // provide our friend, RootsFragment, early access to this special feature!
        if (model == null) {
            return actions;
        }

        return actions.reset(model, searchMode);
    }

    /**
     * Decorates a field that that is injected.
     */
    @Retention(SOURCE)
    @Target(FIELD)
    public @interface Injected {

    }

    /**
     * Decorates a field that holds an object that must be reset in the current content scope
     * (i.e. DirectoryFragment). Fields decorated with this must have an associated
     * accessor on Injector that, when call, reset the object for the calling context.
     */
    @Retention(SOURCE)
    @Target(FIELD)
    public @interface ContentScoped {

    }
}
+10 −2
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.documentsui;

import android.app.Fragment;
import android.view.KeyboardShortcutGroup;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
@@ -27,10 +28,14 @@ import com.android.documentsui.base.Menus;
import com.android.documentsui.base.RootInfo;
import com.android.documentsui.base.State;
import com.android.documentsui.dirlist.DirectoryFragment;
import com.android.documentsui.files.FilesActivity;
import com.android.documentsui.queries.SearchViewManager;
import com.android.documentsui.sidebar.RootsFragment;
import com.android.internal.annotations.VisibleForTesting;

import java.util.List;
import java.util.function.IntFunction;

public abstract class MenuManager {

    final protected SearchViewManager mSearchManager;
@@ -196,6 +201,9 @@ public abstract class MenuManager {
        updateSettings(settings, root);
    }

    public abstract void updateKeyboardShortcutsMenu(
            List<KeyboardShortcutGroup> data, IntFunction<String> stringSupplier);

    protected void updateModePicker(MenuItem grid, MenuItem list) {
        grid.setVisible(mState.derivedMode != State.MODE_GRID);
        list.setVisible(mState.derivedMode != State.MODE_LIST);
@@ -296,9 +304,9 @@ public abstract class MenuManager {
    }

    public static class DirectoryDetails {
        private final BaseActivity<?> mActivity;
        private final BaseActivity mActivity;

        public DirectoryDetails(BaseActivity<?> activity) {
        public DirectoryDetails(BaseActivity activity) {
            mActivity = activity;
        }

Loading