1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/wei.chou-Wei.Lib2A

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
README.md 28 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
gitlife-traslator Отправлено 26.11.2024 22:44 8ae499a

Wei.Lib2A



В 2016 году добавлено следующее:

Полностью новый основанный на @Annotation конфигурационный сэмплер

  • Независимая миграция на GitHub и загрузка в jcenter: Annoguard


Android-библиотека для быстрой разработки, набор инструментов для Android. Задачи управления, загрузки данных и загрузки библиотек см. в других проектах.

Что есть в этой библиотеке? Чем она может нам помочь?

Я пишу код, следуя двум основным принципам:

  • Минимизация объёма кода. Желаемый эффект заключается в том, чтобы пользователь мог максимально уменьшить объём кода, сделать это одной фразой, а не двумя, статическим методом, а не созданием нового объекта;
  • Повышение адаптируемости и стабильности. Из-за фрагментации и множества версий совместимости, разработанных производителями Android, эта библиотека уделяет особое внимание этим факторам, и большинство из них прошли проверку в реальных проектах.

Весь код этой библиотеки был тщательно протестирован автором, структурирован и понятен. Он охватывает все аспекты базовой разработки Android и рекомендуется в качестве основной структуры проекта для удобства интеграции различных функций. Если у вас есть какие-либо вопросы или предложения, пожалуйста, свяжитесь с автором: weichou2010@gmail.com, WeChat или добавление в группу @群主.

Вот краткое описание основных компонентов:

1. Класс инструмента хранения Storage

Несколько констант позволяют легко получить доступ к встроенным или внешним картам памяти Storage.SdCard. Например:

// Вывод пути внешней карты памяти в logcat
if (Storage.CARD_EXT != null) L.i(this, Storage.CARD_EXT.path);

// Можно ли создавать произвольные каталоги на карте по умолчанию
if (Storage.CARD_DEF.isCustomDirCreatable(context)) {
    //...
    try {
        File dir = FileUtils.makeDir(dirPath, true);
        L.i(this, dir.getPath());
        //...
    } catch (FileCreateFailureException e) {
        L.e(this, e);
    }
}

2. Автоматическое определение и хранение карт памяти FStoreLoc

Достаточно ли только инструмента для работы с картами памяти? Ему нужно определить, существует ли карта памяти, можно ли создать каталог и файл, а затем решить, следует ли записывать файл. А [FStoreLoc] может сделать всё за один шаг:

public static File getImagesCacheDir() throws SdCardNotMountedException,
                                SdCardNotValidException, FileCreateFailureException {
    return FStoreLoc.BIGFILE.getImagesCacheDir(get(), DirLevel.CUSTOM);
}

В приведённом выше коде DirLevel.CUSTOM означает выбор пользовательского корневого каталога, который действует только тогда, когда карта памяти поддерживает создание пользовательских каталогов, в противном случае будет выдано исключение. Конечно, вы также можете выбрать частный каталог DirLevel.PRIVATE или адаптивный каталог DirLevel.DEFAULT, подробности см. в документации кода.

У [FStoreLoc] есть три предустановленных режима хранения:

А режимы большого файла и выживания, в зависимости от потребностей бизнеса, могут потребовать настройки корневого каталога карты памяти. В этом случае он будет установлен в приложении:

public class App extends AbsApp {
    @Override
    public void onCreate() {
        Debug.DEBUG = isDebugMode();
        if (Debug.DEBUG) {
            //...
        }
        super.onCreate();
        //...
        /* Установить корневой каталог для режима большого файла. Если корневой каталог карты памяти позволяет записывать файлы, то он создаст этот каталог, иначе он будет использовать частный каталог, выделенный системой для приложения на карте памяти: Android/appname/files/
         * Режим большого файла, т.е. хранить только на встроенной или внешней карте памяти, внешняя карта памяти имеет приоритет.
         */
        FStoreLoc.BIGFILE.setBaseDirName(this, Const.APP_DIR_NAME);
        // Переключиться на внешнюю карту памяти (по умолчанию автоматически выбирается оставшаяся карта с наибольшим пространством). Однако при чтении и записи файлов, если она не существует, она автоматически переключится на встроенную карту.
        FStoreLoc.BIGFILE.switchTo(this, Storage.CARD_EXT);
    }
    //...
}

3. Инструменты для работы с файлами FileUtils и многопроцессные инструменты для параллельного чтения и записи файлов на основе контроля версий FileVersioned 4. Расширенный инструмент SharedPreferences: Keeper

Keeper обладает следующими возможностями:

  • многопроцессное чтение и запись;
  • изоляция файлов на основе Locale.

Базовый способ использования:

public final class XxxKeeper extends Keeper.Wrapper {
    private static final String SPREF_NAME = "spref_name";

    // Ниже приведён фиксированный способ написания кода
    public static WrapperImpl get() {
        return get(AbsApp.get().getApplicationContext(), SPREF_NAME);
    }

    public static final String KEY_VIEW_PEGER_INDEX = "view_peger_index";
    private static final String KEY_XXX_JSON = "xxx_json";
    // ...

    public static void saveXxxObj(XxxObj entity) {
        get()
            .withLocale() // опционально, в зависимости от требований
            .multiProcess() // опционально, в зависимости от требований
            .edit() // опционально, в зависимости от требований
            .keepString(KEY_XXX_JSON, AbsJson.toJsonWithAllFields(entity));
        // Если вышеуказанный API не удовлетворяет требованиям, можно использовать нативный метод
            .getSharedPreferences()
            .putString(KEY_XXX_JSON, AbsJson.toJsonWithAllFields(entity))
            .xxx();
    }

    public static XxxObj getXxxObj() {
        try {
            return AbsJson.fromJsonWithAllFields(
                get()
                .withLocale() // опционально, в зависимости от требований
                .multiProcess() // опционально, в зависимости от требований
                .edit() // опционально, в зависимости от требований
                .readString(KEY_XXX_JSON)
                // Если вышеуказанный API не удовлетворяет требованиям, можно использовать нативный метод
                .getSharedPreferences()
                .getString(KEY_XXX_JSON, null),
                XxxObj.clazz);
        } catch (Exception e) {
            return null;
        }
    }
}

// Или использовать следующим образом:
XxxKeeper.get()
    .withLocale() // опционально, в зависимости от требований
    .multiProcess() // опционально, в зависимости от требований
    .edit() // опционально, в зависимости от требований
    .keepInt(XxxKeeper.KEY_VIEW_PEGER_INDEX, 1);
// Если вышеуказанный API не удовлетворяет требованиям, можно использовать нативный метод
    .getSharedPreferences()
    .putInt(XxxKeeper.KEY_VIEW_PEGER_INDEX, 1)
    .xxx();

5. Определение состояния сетевого подключения Network.

6. Мониторинг состояния сетевого подключения NetConnectionReceiver.

7. Мониторинг состояния подключения к карте памяти StorageReceiver.

Пример:

@Override
protected void onResume() {
    super.onResume();
    NetConnectionReceiver.registerObserver(mNetObserver);
    StorageReceiver.registerObserver(mToastStorageObserver);
    // StorageReceiver.registerObserver(mStorageObserver);
}

@Override
protected void onPause() {
    StorageReceiver.unregisterObserver(mToastStorageObserver);
    // StorageReceiver.unregisterObserver(mStorageObserver);
    NetConnectionReceiver.unregisterObserver(mNetObserver);
    super.onPause();
}

private final NetObserver mNetObserver = new NetObserver() {
    @Override
    public void onChanged(Type type, State state) {
        ensureViewState(true, false);
    }
};

private final ToastStorageObserver mToastStorageObserver = new ToastStorageObserver(this);
private final StorageObserver mStorageObserver = new StorageObserver() {
    /**
     * По нажатию кнопки "MediaButton" отправляется широковещательное сообщение.
     * Если есть кнопка "MediaButton", то Intent.EXTRA_KEY_EVENT содержит объект KeyEvent.
     */
    protected void onMediaButton(KeyEvent ev) {}

    /**
     * Устройство подключено, но не может быть смонтировано.
     */
    protected void onMediaUnMountable(SdCard sdcard) {}

    /**
     * Объект пустой или используется неподдерживаемая файловая система, которая не была отформатирована.
     */
    protected void onMediaNoFS(SdCard sdcard) {}

    /**
     * Носитель данных был подключен и смонтирован. intent содержит логическое значение read-only, которое указывает, является ли точка монтирования доступной только для чтения.
     */
    protected void onMediaMounted(SdCard sdcard, boolean readOnly) {}

    /**
     * Идёт проверка диска.
     */
    protected void onMediaChecking(SdCard sdcard) {}

    /**
     * Запрос на сканирование носителя данных с помощью сканера, чтобы поместить информацию о медиафайлах в базу данных.
     */

}
``` view == ((ViewHolder<?, ?>)obj).getView();

    @Override
    public int getItemPosition(Object obj) {
        int position = super.getItemPosition(obj);
        if (obj instanceof ViewHolder4) {
            position = 4;
        } else if (obj instanceof ViewHolder3) {
            position = 3;
        } else if (obj instanceof ViewHolder2) {
            position = 2;
        } else if (obj instanceof ViewHolder1) {
            position = 1;
        } else if (obj instanceof ViewHolder0) {
            position = 0;
        }
        return position;
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        ViewHolder<Void, OnClickListener> vHolder = null;
        switch (position) {
            case 0:
                vHolder = ViewHolder.bindView(0, ViewHolder.makeView(ViewHolder0.class, getLayoutInflater(), container), ViewHolder0.class, null, mOnNextClick);
                break;
            case 1:
                vHolder = ViewHolder.bindView(0, ViewHolder.makeView(ViewHolder1.class, getLayoutInflater(), container), ViewHolder1.class, null, mOnNextClick);
                break;
            case 2:
                vHolder = ViewHolder.bindView(0, ViewHolder.makeView(ViewHolder2.class, getLayoutInflater(), container), ViewHolder2.class, null, mOnNextClick);
                break;
            case 3:
                vHolder = ViewHolder.bindView(0, ViewHolder.makeView(ViewHolder3.class, getLayoutInflater(), container), ViewHolder3.class, null, mOnNextClick);
                break;
            case 4:
                vHolder = ViewHolder.bindView(0, ViewHolder.makeView(ViewHolder4.class, getLayoutInflater(), container), ViewHolder4.class, null, mOnCompleteClick);
                break;
        }
        container.addView(vHolder.getView());
        return vHolder;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object obj) {
        container.removeView(((ViewHolder<?, ?>)obj).getView());
    }
});
//...

@ViewLayoutId(R.layout.i_m_guide_next)
private static class ViewHolder0 extends ViewHolder<Void, OnClickListener> {
    @ViewId(R.id.i_m_guide_bg)
    protected View mBg;
    @ViewId(R.id.i_m_guide_btn_next)
    protected ImageButton mBtnNext;

    protected static final int WIDTH        = 720;
    protected static final int HEIGHT       = 1280;
    protected static final int WIDTH_BTN    = 224;
    protected static final int HEIGHT_BTN   = 88;
    protected static final int RIGHT_BTN    = 16;
    protected static final int BOTTOM_BTN   = 29;

    public ViewHolder0(View view) {
        super(view);
    }

    @Override
    protected void init(OnClickListener... args) {
        mBg.setBackgroundResource(R.drawable.img_i_m_guide_0);
        mBtnNext.setTag(0);
        mBtnNext.setOnClickListener(args[0]);
        initBtnNextPosition();
    }

    @Override
    public void bind(int position, Void data) {}

    protected void initBtnNextPosition() {
        int screenWidth = Device.getInstance(getView().getContext()).width;
        int screenHeight = Device.getInstance(getView().getContext()).height;
        RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) mBtnNext.getLayoutParams();
        float widthScale = screenWidth * 1.0f / WIDTH;
        float heightScale = screenHeight * 1.0f / HEIGHT;
        lp.width = (int) (widthScale * WIDTH_BTN);
        lp.height = (int) (heightScale * HEIGHT_BTN);
        lp.rightMargin = (int) (widthScale * RIGHT_BTN);
        lp.bottomMargin = (int) (heightScale * BOTTOM_BTN);
        mBtnNext.setLayoutParams(lp);
    }
} Вот перевод текста на русский язык:

static class ViewHolder1 extends ViewHolder0 { public ViewHolder1(View view) { super(view); }

@Override
protected void init(OnClickListener... args) {
    mBg.setBackgroundResource(R.drawable.img_i_m_guide_1);
    mBtnNext.setTag(1);
    mBtnNext.setOnClickListener(args[0]);
    initBtnNextPosition();
}

} //...


Также может использоваться в других сценариях:

```Java

public class Xxx {
    @Override
    public void onClick(View v) {
        // Вывести диалоговое окно удаления
        FavoriteDeleteViewHolder.showDeleteDialog(FavoriteActy.this, (ViewGroup) getWindow().getDecorView(), mOnDeleteClick);
    }
    //...
}

@ViewLayoutId(R.layout.m_favorite_delete_panel)
public class FavoriteDeleteViewHolder extends ViewHolder<Void, OnClickListener> {
    @ViewId(R.id.m_favorite_delete_panel_content)
    private ViewGroup mContentView;
    @ViewId(R.id.m_favorite_delete_panel_btn_delete)
    private Button mBtnDelete;
    @ViewId(R.id.m_favorite_delete_panel_btn_cancel)
    private Button mBtnCancel;

    private Context mContext;
    private OnClickListener mOnDeleteClickCallback;
    private boolean mDelete;

    public FavoriteDeleteViewHolder(View view) {
        super(view);
        mContext = view.getContext();
    }

    public static FavoriteDeleteViewHolder showDeleteDialog(Activity context, ViewGroup parent, OnClickListener onDeleteClickCallback) {
        View view = FavoriteDeleteViewHolder.makeView(FavoriteDeleteViewHolder.class, context.getLayoutInflater(), parent);
        FavoriteDeleteViewHolder vHolder = FavoriteDeleteViewHolder.bindView(0, view, FavoriteDeleteViewHolder.class, null, onDeleteClickCallback);
        parent.addView(view);
        vHolder.startAnimIn();
        return vHolder;
    }

    public void destroy() {
        startAnimOut();
    }
    //...
}
  • Это просто потрясающе, не так ли?!!!

12. Выбор изображения из галереи, обрезка и сохранение изображения в галерее с последующим обновлением PhotoUtils

Пример:


private static final String EXTRA_SESSION           = ContributeActy.class.getName() + ".SESSION";
private static final String EXTRA_LIST_DATA         = ContributeActy.class. getName() + ".LIST_DATA";

private static final int REQUEST_CODE_PICK_PHOTO    = 100;
private static final int REQUEST_CODE_CROP          = 101;

private PhotoUtils.Session session;
//...

@Override
public void onClick(View v) {
    try {
        session = PhotoUtils.openSysGallery2ChoosePhoto(ContributeActy.this, REQUEST_CODE_PICK_PHOTO,
            new CropArgs(REQUEST_CODE_CROP,
                new File(App.getImagesCacheDirPrivate(), "croptemp-" + System.currentTimeMillis() + ".png").getPath(),
                Bitmap.CompressFormat.PNG, false, true, 0, 0, 0, 0, 640, 640));
        L.i(ContributeActy.class, session.toString());
    } catch (Exception e) {
        L.e(ContributeActy.class, e);
    }
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    Uri uri = PhotoUtils.onActivityResult(this, session, requestCode, resultCode, data);
    if (uri != null) {
        getAdapter().getData().add(uri);
        getAdapter().notifyDataSetChanged();
        session = null;
    }
}

@Override
protected void onSaveInstanceState(Bundle outState) {
    List<Uri> data = getAdapter().getData();
    if (data.size() > 0) {
        ArrayList<String> value = new ArrayList<String>();
        for (Uri uri : data) {
            value.add(uri.toString());
        }
        outState.putStringArrayList(EXTRA_LIST_DATA, value);
    }
    if (session != null) outState.putString(EXTRA_SESSION, session.toJson());
    super.onSaveInstanceState(outState);
}

@Override
``` **13. Абстракция ListView и аналогичных компонентов для обновления данных**

```Java
protected void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
    ArrayList<String> value = savedInstanceState.getStringArrayList(EXTRA_LIST_DATA);
    if (value != null && value.size() > 0) {
        List<Uri> data = new ArrayList<Uri>();
        for (String s : value) {
            data.add(Uri.parse(s));
        }
        getAdapter().setDataSource(data);
    }
    String json = savedInstanceState.getString(EXTRA_SESSION);
    if (json != null) session = Session.fromJsonWithAllFields(json, Session.class);
}

Абстрактный класс AbsListViewActivity, абстрактный фрагмент AbsListViewFragment и абстрактный адаптер AbsAdapter используются для упрощения обновления данных в компонентах типа ListView.

14. Инструменты для работы с изображениями BitmapUtils

В этом разделе не представлен код на Java.

15. Инструмент для чтения свойств из AndroidManifest.xml Manifest

В этом разделе не представлен код на Java.

16. Диалоговые окна, всплывающие окна и индикаторы выполнения DialogHelper, Prompt и PromptProgress

Инструменты DialogHelper, Prompt и PromptProgress позволяют настраивать диалоги, всплывающие окна и индикаторы прогресса. Они предоставляют возможность настройки пользовательского интерфейса и анимации. DialogHelper также позволяет отображать диалоговые окна на рабочем столе.

17. Текст с гиперссылками LinkMovementMethod и LinkSpan

Этот раздел не содержит кода на Java. Он описывает инструменты LinkMovementMethod и LinkSpan, которые обеспечивают эффект клика по гиперссылке в тексте.

18. Приложение с возможностью отслеживания выхода AbsApp

Класс App расширяет класс AbsApp и переопределяет метод onExit(). В этом методе выполняется необходимая логика перед выходом из приложения. Метод super.onExit() вызывает реализацию метода onExit() родительского класса. Если mExitForRestart имеет значение true, то после выхода из приложения будет запущен WelcomeActy.startMe().

public class App extends AbsApp {
    @Override
    protected boolean onExit() {
        L.i(this, "Программа нормально завершает работу------App.onExit()");
        //...
        super.onExit();
        if (mExitForRestart) {
            WelcomeActy.startMe(this);
            mExitForRestart = false;
        }
        return false;
    }
}

19. Инструмент для генерации асимметричных ключей RsaUtils

RsaUtils — это инструмент для генерации асимметричных пар ключей. Он может создавать пары ключей, которые могут быть распознаны iOS-проектами.

20. Временные инструменты TimeUtils

TimeUtils предоставляет различные функции для работы со временем. Он может анализировать нестандартные форматы времени, вычислять возраст по дате рождения, генерировать время без часового пояса и предоставлять информацию о времени суток.

21. Упрощённый логгер L

L — это упрощённый логгер, который позволяет оптимизировать логирование в релизных сборках путём удаления низкоуровневых сообщений. Это достигается за счёт использования аннотаций Burden или настройки Proguard.

22. Глобальный обработчик исключений CrashHandler

CrashHandler — это глобальный обработчик исключений, который может выполнять дамп памяти в файл .hprof для анализа памяти. Можно перехватить определённое или все исключения для некоторого потока;

  • можно перехватить определённое или все исключения для всех потоков;
  • способ обработки после перехвата должен быть настроен в соответствии с потребностями бизнеса, по умолчанию происходит аварийное завершение работы.

23. Полностью новая библиотека настроек запутывания на основе @Annotation

Связаться с автором

微信 支付宝

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/wei.chou-Wei.Lib2A.git
git@api.gitlife.ru:oschina-mirror/wei.chou-Wei.Lib2A.git
oschina-mirror
wei.chou-Wei.Lib2A
wei.chou-Wei.Lib2A
master