برمجة تعريفية لتطبيقات خادم العميل على android. الجزء 2

في المادة السابقة أظهرت لفترة وجيزة مزايا برمجة تعريفية تطبيقات خدمة العملاء لالروبوت بالمقارنة مع حتمية.

الآن سنكتب مشروعًا صغيرًا ولكنه كافٍ لتقييم فعالية مكتبة DePro. وهي جزء من أحد الأمثلة التعليمية للمكتبة . يتم عرض تصميم جميع الشاشات التي نصفها في الأشكال التالية:

صورة صورة صورة
DRAWER شاشة CATALOG شاشة PRODUCT_LIST

صورة صورة صورة
 CATALOG_           DESCRIPT          CHARACTERISTIC

صورة صورة صورة
 FITNESS           FITNESS_          


من هذه الشاشات ، يتم فهم وظائفها بشكل عام. تحتوي القائمة الجانبية على عنصرين "كتالوج" و "لياقة". عند تحديد عنصر ، يتم عرض الشاشة المقابلة. تحتوي شاشة كتالوج على قائمة "أخبار" أفقية. عند النقر على أي "منتج جديد" ، يتم عرض شاشة تحتوي على وصف لهذا المنتج. يتكون الوصف من علامتي تبويب: "الوصف" و "الخصائص". أيضا على شاشة كتالوج هناك قائمة منسدلة "كتالوج". عند النقر على السهم لأسفل ، يفتح الدليل (يغلق). عند النقر فوق السطر بالكامل ، يتم عرض شاشة PRODUCT_LIST مع قائمة المنتجات للعنصر المحدد في الكتالوج.

عند النقر فوق عنصر "اللياقة البدنية" ، يتم عرض شاشة اللياقة مع قائمة من الخدمات. القائمة تعتمد على النادي المختار في الدوار. عند محاولة الخروج من التطبيق ، يتم عرض مربع حوار تحذير.

ينقل الخادم البيانات بتنسيق json إلى التطبيق. يتم وصف هيكل البيانات لكل شاشة أدناه. في التطبيقات المكتوبة في DePro من واجهة برمجة التطبيقات (API) ، يتم استخدام عنوان URL فقط ، وهيكل البيانات مطلوب فقط لتعيين عرض الاسم (id) بشكل صحيح ، لأن الربط يتم بالاسم. تجدر الإشارة إلى أن البيانات عبارة عن شريحة غير مكتملة من البيانات الحقيقية. لذلك ، قد لا يكون هناك اتصالات على الأسماء والصور. على وجه الخصوص ، إجمالي صور المنتج 20 جهاز كمبيوتر شخصى. لذلك ، يمكن أن تكون الصورة نفسها في العديد من المنتجات.

API لشاشات سبيل المثال
CATALOG () URL depro/cron/news, GET. . .



    {
        "product_id":4610,
        "catalog_id":15984,
        "product_name":"  20  6  ( 1*20) APRO",
        "catalog_code":"ZRG-20kit",
        "picture":"depro/cronimg/picture_1.jpeg",
        "bar_code":"4824041010653",
        "oem":"",
        "price":175.98,
        "brand":"APRO",
        "product_code":"032578",
        "gift":0,
        "bonus":0,
        "new_product":1,
        "quantity":5
    },
    . . .

URL depro/cron/catalog.

URL depro/cron/catalog_ex catalog_id id , .

:

[
    {
        "catalog_id":15510,
        "parent_id":0,
        "catalog_name":""
    },
    {
        "catalog_id":15584,
        "parent_id":0,
        "catalog_name":""
    },
    . . .
]

PRODUCT_LIST URL depro/cron/product_list : expandedLevel catalog_id.
expandedLevel — (0, 1 2), catalog_id — id .

0 1 , , .

GET

()

URL depro/cron/product_barcode
barcode_scanner.

URL depro/cron/product_search product_name. LIKE. product_name .

.

DESCRIPT

: URL depro/cron/product_id product_id. GET.



{
    "product_id":2942,
    "catalog_id":15594,
    "product_name":"   2110, 2111, 2112,  Sens ''  ",
    "catalog_code":"23.3828"
    ,"picture":"depro/cronimg/picture_16.jpeg",
    "bar_code":"2000000148472",
    "oem":"2112-3851010",
    "price":103.02,
    "brand":", . , ",
    "product_code":"027729",
    "gift":1,
    "bonus":0,
    "new_product":0,
    "quantity":16
}

: URL depro/cron/product_analog product_id. GET.



[
    {
        "product_id":561,
        "catalog_id":15587,
        "product_name":"   2110, 2111, 2112 (  16 . ) AURORA",
        "catalog_code":"WP-LA2112",
        "picture":"depro/cronimg/picture_12.jpeg",
        "bar_code":"2900011680711",
        "oem":"2112-1307010",
        "price":188.16,
        "brand":"AURORA, Poland",
        "product_code":"016807",
        "gift":0,
        "bonus":1,
        "new_product":0,
        "quantity":15
    },
    . . .
]


CHARACTERISTIC URL depro/cron/product_charact product_id. GET.


[
    {
        "prop_id":2764,
        "product_id":2942,
        "name":"",
        "value":", . , "
    },
    {
        "prop_id":2765,
        "product_id":2942,
        "name":"   ",
        "value":","
    },
    . . .
]


الآن فكر في خطواتنا لكتابة طلب.

1. في الاستوديو سنقوم بإنشاء مشروع جديد. يمكن تعيين الاسم حسب تقديرك.

2. نشر الموارد. كما ذكر في المقال الأول ، يتم استخدام ملفات الموارد (XML) بشكل تقليدي. لذلك ، حتى لا نضيع الوقت في الأشياء المعروفة ، نقوم ببساطة بتنزيل جميع الموارد اللازمة .

قم بفك ضغط ملف res_example.zip الناتج. في الاستوديو ، احذف محتويات المجلد res بالكامل.

انقل محتويات المجلد res غير المضغوط إلى مجلد res الخاص بالمشروع. بعد ذلك ، مع مراعاة ميزات Android Studio ، قد تحتاج إلى مسح المشروع و / أو تشغيل أمر التخزين المؤقت / إعادة التشغيل غير الصالح.

3. توصيل المكتبة

في قسم التبعيات في ملف build.gradle للوحدة ، تحتاج إلى تحديد:

    implementation 'github.com/deprosystem/depro:compon:3.0.1'

في قسم android من ملف build.gradle للوحدة ، تحتاج إلى تحديد:

    packagingOptions {
        exclude 'META-INF/DEPENDENCIES'
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

عند اختيار سمة minSdkVersion ، يجب أن تأخذ في الاعتبار أن المكتبة تدعم minSdkVersion = 17. بعد تغيير build.gradle ، تحتاج إلى مزامنة المشروع.

4. إنشاء الفئات (الملفات) اللازمة. عند العمل مع المكتبة ، يتم استخدام 4 فئات فقط: MyDeclareScreens - يتم وصف جميع الشاشات ؛ MyParams - تعيين المعلمات اللازمة للتطبيق ؛ MyApp - بدأت مكتبة DePro ؛ النشاط الرئيسي - بدء النشاط. يمكنك استخدام أسماء الصف الخاصة بك.

قم بإنشاء فئة MyDeclareScreens.java. محتوياتها هي كما يلي:

public class MyDeclareScreens extends DeclareScreens {

    public final static String
            MAIN = "main", DRAWER = "DRAWER", CATALOG = "CATALOG",
            DESCRIPT = "DESCRIPT", CHARACTERISTIC = "CHARACTERISTIC",
            PRODUCT_LIST = "PRODUCT_LIST", PRODUCT_DESCRIPT = "PRODUCT_DESCRIPT",
            FITNESS = "FITNESS";

    @Override
    public void declare() {
        activity(MAIN, R.layout.activity_main)
                .navigator(finishDialog(R.string.attention, R.string.finishOk))
                .drawer(R.id.drawer, R.id.content_frame, R.id.left_drawer, null, DRAWER);

        fragment(DRAWER, R.layout.fragment_drawer)
                .menu(model(menu), view(R.id.recycler));

        fragment(CATALOG, R.layout.fragment_catalog)
                .navigator(handler(R.id.back, VH.OPEN_DRAWER))
                .component(TC.RECYCLER_HORIZONTAL, model(Api.NEWS_PROD).pagination().progress(R.id.progr),
                        view(R.id.recycler_news, R.layout.item_news_prod),
                        navigator(start(PRODUCT_DESCRIPT)))
                .component(TC.RECYCLER, model(Api.CATALOG),
                        view(R.id.recycler, "expandedLevel", new int[]{R.layout.item_catalog_type_1,
                                R.layout.item_catalog_type_2, R.layout.item_catalog_type_3})
                                .expanded(R.id.expand, R.id.expand, model(Api.CATALOG_EX, "catalog_id")),
                        navigator(start(PRODUCT_LIST)));

        activity(PRODUCT_LIST, R.layout.activity_product_list, "%1$s", "catalog_name").animate(AS.RL)
                .navigator(back(R.id.back))
                .component(TC.RECYCLER, model(Api.PRODUCT_LIST, "expandedLevel,catalog_id"),
                        view(R.id.recycler, R.layout.item_product_list)
                                .visibilityManager(visibility(R.id.bonus_i, "bonus"),
                                        visibility(R.id.gift_i, "gift"),
                                        visibility(R.id.newT, "new_product")),
                        navigator(start(PRODUCT_DESCRIPT)));

        activity(PRODUCT_DESCRIPT, R.layout.activity_product_descript, "%1$s", "catalog_name").animate(AS.RL)
                .navigator(back(R.id.back))
                .setValue(item(R.id.product_name, TS.PARAM, "product_name"))
                .component(TC.PAGER_F, view(R.id.pager, DESCRIPT, CHARACTERISTIC)
                        .setTab(R.id.tabs, R.array.descript_tab_name));

        fragment(DESCRIPT, R.layout.fragment_descript)
                .component(TC.PANEL, model(Api.PRODUCT_ID, "product_id"),
                        view(R.id.panel).visibilityManager(visibility(R.id.bonus, "bonus")))
                .component(TC.RECYCLER, model(Api.ANALOG_ID_PRODUCT,"product_id"),
                        view(R.id.recycler, R.layout.item_product_list).noDataView(R.id.not_analog)
                                .visibilityManager(visibility(R.id.bonus_i, "bonus"),
                                        visibility(R.id.gift_i, "gift"),
                                        visibility(R.id.newT, "new_product")),
                        navigator(start(0, PRODUCT_DESCRIPT, PS.RECORD),
                                handler(0, VH.BACK))) ;

        fragment(CHARACTERISTIC, R.layout.fragment_characteristic)
                .component(TC.RECYCLER, model(Api.CHARACT_ID_PRODUCT, "product_id"),
                        view(R.id.recycler, "2", new int[] {R.layout.item_property, R.layout.item_property_1}));

        fragment(FITNESS, R.layout.fragment_fitness)
                .navigator(handler(R.id.back, VH.OPEN_DRAWER))
                .component(TC.SPINNER, model(JSON, getString(R.string.clubs)),
                        view(R.id.spinner, R.layout.item_spin_drop, R.layout.item_spin_hider))
                .component(TC.RECYCLER, model(Api.FITNESS, "clubId"),
                        view(R.id.recycler, R.layout.item_fitness), null).eventFrom(R.id.spinner);
    }

    Menu menu = new Menu()
            .item(R.drawable.list, R.string.m_catalog, CATALOG, true)
            .divider()
            .item(R.drawable.ic_aura, R.string.fitness, FITNESS);
}

سنصف لاحقًا جميع تركيبات DePro المستخدمة. لتوصيل الاستيراد ، استخدم مفاتيح alt + enter. سيتم أيضًا تمييز اللون الأحمر في فئة Api حيث يتم تعيين عناوين جميع الطلبات. سيتم إعطاء محتوياته في وقت لاحق.

قم بإنشاء فئة MyParams.java. في معظم الحالات ، تكون الإعدادات الافتراضية كافية. في حالتنا ، سنقوم بتعيين عنوان URL الأساسي فقط.

public class MyParams extends AppParams {
    @Override
    public void setParams() {
        baseUrl = "https://deprosystem.com/";
    }
}

قم بتغيير المحتوى الذي تم إنشاؤه بواسطة استوديو فئة MainActivity إلى ما يلي:

public class MainActivity extends BaseActivity {
    @Override
    public String getNameScreen() {
        return MyDeclareScreens.MAIN;
    }
}

في بيان MainActivity ، يمكنك تحديد اتجاه عمودي. من حيث المبدأ ، تدعم المكتبة دوران الشاشة ، ولكن في هذا الإصدار لشاشات نوع النشاط () ، بصرف النظر عن البداية ، يتم وصف الاتجاه الرأسي أيضًا.

إنشاء فئة MyApp:

public class MyApp extends Application {
    private static MyApp instance;
    private Context context;

    public static MyApp getInstance() {
        if (instance == null) {
            instance = new MyApp();
        }
        return instance;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        instance = this;
        context = getApplicationContext();

        DeclareParam.build(context)
                .setAppParams(new MyParams())
                .setDeclareScreens(new MyDeclareScreens());
    }
}

هذا أمر فردي منتظم في طريقة onCreate التي يتم تعيين MyParams و MyDeclareScreens لها.
تذكر أن تصف MyApp في البيان.

للإنهاء ، قم بإنشاء فئة Api:

public class Api {
    public static final String CATALOG = "depro/cron/catalog",
            NEWS_PROD = "depro/cron/news_prod",
            PRODUCT_LIST = "depro/cron/product_list",
            PRODUCT_ID = "depro/cron/product_id",
            ANALOG_ID_PRODUCT = "depro/cron/product_analog",
            CHARACT_ID_PRODUCT = "depro/cron/product_charact",
            FITNESS = "depro/cron/fitness",
            CATALOG_EX = "depro/cron/catalog_ex";
}

5. الآن يمكنك تشغيل التطبيق للتنفيذ.

إذا تم إدخال كل شيء بشكل صحيح ، فعند بدء التطبيق ، سيتم عرض جميع الشاشات المحددة (والعمل).

كما نرى ، لدينا فقط خمسة فصول بسيطة للتطبيق بالكامل. وأربعة منهم مساعد. محتوياتها مستقلة عن عدد الشاشات. كما أن وصف الشاشات ، بشكل عام ليس تافهًا ، يشغل مساحة صغيرة (أقل من 80 سطرًا). الآن نظهر أن الوصف ليس كبيرًا فحسب ، ولكنه ليس معقدًا أيضًا. للقيام بذلك ، وصفنا تشغيل مكونات المكتبة المستخدمة.

كما هو موضح في المقالة الأولى ، يمكن أن تكون الشاشات في المكتبة إما نشاطًا أو جزءًا ، مما يحدد اسم الشاشة (السطر) والتخطيط. روابط للشاشات مصنوعة بأسمائهم. يتم اختيار نوع الشاشة التي سيتم استخدامها بالطريقة المعتادة.

الشاشة الرئيسية

لذلك ، من التصميم يمكن ملاحظة أن شاشة البدء تحتوي على قائمة جانبية وحاوية للأجزاء. في ترميز R.layout.activity_main ، يتم تعيين DrawerLayout قياسي. لذلك ، في وصف الشاشة الرئيسية ، نحدد مكون الدرج ، الذي نقوم بتمرير معرف DrawerLayout نفسه وحاوياته للشريط الجانبي والأجزاء. نشير أيضًا إلى اسم الشاشة (DRAWER) ، التي سيتم عرضها في الشريط الجانبي. يشير المتصفح finishDialog إلى أنه قبل الخروج من التطبيق تحتاج إلى إصدار مربع حوار تأكيد.

شاشة DRAWER

تحتوي على مكون قائمة واحد فقط مع متغير نوع القائمة المحدد في النموذج ، وعنصر ترميز نوع RecyclerView في عرض المعرف ، والذي سيعرض القائمة. تشير القائمة نفسها إلى أنه سيتم عرض عنصر القائمة "CATALOG" في حاوية الأجزاء عند بدء تشغيل القائمة.

شاشة كتالوج

تحتوي على قائمة جديدة أفقية واحدة. عند استلام البيانات من الخادم ، يستخدم نموذجه ترقيم الصفحات ويعرض التقدم في R.id.progr. إذا كان الإنترنت سريعًا ، فقد لا تلاحظ ظهور لوحة تقدم. إذا كنت ترغب في مشاهدته ، يمكنك التبديل إلى إنترنت أبطأ ، أو تغيير لون خلفية R.id.progr. في هذه الحالة ، ستراه على الأقل يومض. بالنسبة لترقيم الصفحات ، يتم استخدام المعلمات المحددة في AppParams بشكل افتراضي. يتم إعطاء العرض R.id.recycler_news مع RecyclerView وتخطيط للعناصر. عند النقر فوق أي عنصر في القائمة ، تبدأ شاشة PRODUCT_DESCRIPT.

قائمة الدليل هي قائمة منسدلة. يتم تعريف مستوى الإفشاء في حقل "المستوى الموسع". إذا لم يتم إرسالها مع بيانات المصدر ، فستتعامل المكتبة نفسها مع ذلك. تحدد نفس المعلمة أي تخطيط من القائمة يتم استخدامه في كل مستوى من مستويات الإفشاء. حقيقة أن القائمة المنسدلة تخدم الوظيفة الموسعة (...) سيتم تعيين النموذج في الكاتور لتلقي البيانات من الخادم للمستويات التالية. يحدد النموذج عنوان طلب Api.CATALOG_EX واسم معلمة الطلب "catalog_id". في الموسع ، يشار إلى R.id.expand أيضًا - عنصر ترميز في العناصر عن طريق النقر على القائمة التي سيتم توسيعها ومعرف العنصر الذي سيتم تدويره بشكل متحرك بمقدار 180 درجة عند التوسيع - إغلاق القائمة. وأخيرًا ، يشير المستكشفأنه عند النقر فوق عنصر القائمة ، سيتم استدعاء شاشة PRODUCT_LIST.

يشير المستكشف ، الذي يشير إلى الشاشة بأكملها ، إلى أنه عند النقر فوق عنصر R.id.back ، سيتم فتح لوحة جانبية.

شاشة PRODUCT_LIST

عند تحديد الشاشة ، يشار إلى أن القيمة الحالية لمعلمةatalog_name ستظهر في الرأس وستكون الرسوم المتحركة الناتجة من اليمين إلى اليسار (AS.RL). وصف القائمة مألوف لنا بالفعل. الشيء الوحيد للعرض التقديمي هو visibilityManager ، الذي يتحكم في رؤية عناصر الترميز اعتمادًا على قيم البيانات المقابلة. يشير المستكشف المرتبط بالشاشة بأكملها إلى أنه عند النقر فوق عنصر R.id.back ، سيتم إرجاعك إلى الشاشة السابقة.

شاشة PRODUCT_DESCRIPT

الجديد بالنسبة لنا هو مكون من النوع PAGER_F. وهي مرتبطة ببرنامج ViewPager العادي. يتم عرض قائمة الشاشات (الأجزاء) التي سيتم عرضها ، ويتم توصيل TabLayout (setTab). تظهر

شاشة PRODUCT_DESCRIPT في علامة التبويب DESCRIPTION.

يعرض أحد مكونات نوع PANEL البيانات التي حصل عليها النموذج. تعرض قائمة "النظائر" قائمة بالمنتجات المماثلة ، إن وجدت ، أو باستخدام وظيفة noDataView () ، تظهر رسالة "النظير مفقودة".

شاشة الخصائص

تعرض قائمة بميزات المنتج.

شاشة الملاءمة

يعرض مكون من النوع SPINNER قائمة بالأندية مع خيار تحديد أحد الأندية. يتم تعيين قائمة الأندية في النموذج كسلسلة json.

قائمة فئات الفئات أمر طبيعي. تشير الدالة eventFrom (...) إلى أنه عند تغيير المكون المرتبط بـ R.id.spinner (في حالتنا ، spiner) ، من الضروري تحديث البيانات.
يمكن الاطلاع على رمز التطبيق الذي تمت مناقشته في المقالة على Github .

المقالة للتوجيه فقط. أكثر اكتمالا مع قدرات مكتبة DePro متاح في الوثائق .

All Articles