مشاوره رایگان
دریافت لینک های دانلود دریافت پستی درب منزل مبلغ کل: تومان
جهت دریافت کد تخفیف به کانال تلگرام مراجعه و یا با پشتیبان آنلاین هماهنگ نمایید

ViewModel در اندروید


ViewModel در اندروید

 

در این آموزش ، ما مفهوم ViewModel را به شکل عمیق و کامل بررسی خواهیم کرد. برنامه اندرویدی می سازیم که بتواند لینک های مورد علاقه کاربر را در پایگاه داده SQLite ذخیره کند و خواهیم دید که ViewModel چگونه در ساخت یک برنامه قوی به ما کمک می کند.

ViewModel جزئی از مجموعه مولفه های معماری اندروید (Android architecture component) است و به عنوان مدیر داده ها در برنامه استفاده می شود.

اجازه دادن به اکتیویتی برای انجام کار با داده ها اصلاً ایده خوبی نیست. ViewModel راهی برای ایجاد و تحویل داده ها و اشیا (Objects) فراهم می کند. ViewModel معمولاً وضعیت داده های View را  ذخیره می کند و با سایر مولفه های (Components) برنامه ارتباط برقرار می کند.

وقتی صحبت از تغییرات پیکربندی می شود (مثلاً وقتی گوشی را می چرخانیم) و اطلاعات Activity پاک می شوند ، ViewModel مفید است. تغییر پیکربندی بر ViewModel تأثیر نمی گذارد زیرا ViewModel کاملاً به Activity وابسته نیست. ViewModel قادر است داده ها را پس از بازآفرینی مجدداً در اختیار Activity قرار دهد.

قانون ساده: اجازه ندهید Activity ها همه کارها را انجام دهند. خصوصاً در مورد داده ها.

 

SQLite در اندروید

 

همانطور که در بالا گفته شد «  اجازه ندهید Activity ها همه کارها را انجام دهند » در اینجا ما کوئری های SQLite را در کلاس ViewModel خود انجام می دهیم.

برای افزودن داده به پایگاه داده SQLite ، ما از یک ContentValue استفاده می کنیم که مانند یک ذخیره ساز موقت یا نگهدارنده برای داده ها است. ما داده ها را به صورت یک جفت مقدار-کلید درون شی ContentValue انتقال می دهیم.

برای بازیابی داده ها از SQLite نیز از یک شی Cursor استفاده می شود.

در زیر ، ما برنامه ای ایجاد خواهیم کرد که رکوردهای ListView را در یک جدول SQLite نگهداری می کند.

در این برنامه شما می توانید پیوندهای وب مورد علاقه خود را به ListView اضافه کنید / حذف کنید. این پیوند ها از طریق ViewModel در پایگاه داده به روز می شود.

 

ساختار پروژه آموزشی  ViewModelدر اندروید

 

در تصویر زیر ساختار پروژه را می بینید:

 

 

کتابخانه های زیر را در فایل build.gradle در ماژول app در برنامه خود اضافه کنید:

implementation 'com.android.support:design:27.1.1'
implementation "android.arch.lifecycle:extensions:1.1.1"

 

پیاده سازی برنامه

 

تنظیمات SQLite داخل پوشه DB است. کد کلاس DbSettings.java در زیر آورده شده است:

package com.journaldev.androidviewmodel.db;

import android.provider.BaseColumns;

public class DbSettings {

    public static final String DB_NAME = "favourites.db";
    public static final int DB_VERSION = 1;

    public class DBEntry implements BaseColumns {

        public static final String TABLE = "fav";
        public static final String COL_FAV_URL = "url";
        public static final String COL_FAV_DATE = "date";

    }
}

 

کد کلاس FavouritesDbHelper.java در زیر آورده شده است:

package com.journaldev.androidviewmodel.db;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class FavouritesDBHelper extends SQLiteOpenHelper {

    public FavouritesDBHelper(Context context) {
        super(context, DbSettings.DB_NAME, null, DbSettings.DB_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        String createTable = "CREATE TABLE " + DbSettings.DBEntry.TABLE + " ( " +
                DbSettings.DBEntry._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
                DbSettings.DBEntry.COL_FAV_URL + " TEXT NOT NULL, " +
                DbSettings.DBEntry.COL_FAV_DATE + " INTEGER NOT NULL);";
        db.execSQL(createTable);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("DROP TABLE IF EXISTS " + DbSettings.DBEntry.TABLE);
        onCreate(db);
    }

}

جدول ما شامل سه ستون است: ID  و URL  و DATE.

 

کد کلاس Favourites.java در زیر آورده شده است:

package com.journaldev.androidviewmodel;

public class Favourites {

    public long mId;
    public String mUrl;
    public long mDate;

    public Favourites(long id, String name, long date) {
        mId = id;
        mUrl = name;
        mDate = date;
    }

    public Favourites(Favourites favourites) {
        mId = favourites.mId;
        mUrl = favourites.mUrl;
        mDate = favourites.mDate;
    }

}

 

کد کلاس FavouritesViewModel.java در زیر آورده شده است:

package com.journaldev.androidviewmodel;

import android.app.Application;
import android.arch.lifecycle.AndroidViewModel;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;

import com.journaldev.androidviewmodel.db.DbSettings;
import com.journaldev.androidviewmodel.db.FavouritesDBHelper;


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

public class FavouritesViewModel extends AndroidViewModel {

    private FavouritesDBHelper mFavHelper;
    private ArrayList<Favourites> mFavs;

    FavouritesViewModel(Application application) {
        super(application);
        mFavHelper = new FavouritesDBHelper(application);
    }

    public List<Favourites> getFavs() {
        if (mFavs == null) {
            mFavs = new ArrayList<>();

            createDummyList();
            loadFavs();
        }
        ArrayList<Favourites> clonedFavs = new ArrayList<>(mFavs.size());
        for (int i = 0; i < mFavs.size(); i++) {
            clonedFavs.add(new Favourites(mFavs.get(i)));
        }
        return clonedFavs;
    }

    public void createDummyList() {

        addFav("https://www.journaldev.com", (new Date()).getTime());
        addFav("https://www.medium.com", (new Date()).getTime());
        addFav("https://www.reddit.com", (new Date()).getTime());
        addFav("https://www.github.com", (new Date()).getTime());
        addFav("https://www.hackerrank.com", (new Date()).getTime());
        addFav("https://www.developers.android.com", (new Date()).getTime());
    }

    private void loadFavs() {

        mFavs.clear();

        SQLiteDatabase db = mFavHelper.getReadableDatabase();
        Cursor cursor = db.query(DbSettings.DBEntry.TABLE,
                new String[]{
                        DbSettings.DBEntry._ID,
                        DbSettings.DBEntry.COL_FAV_URL,
                        DbSettings.DBEntry.COL_FAV_DATE
                },
                null, null, null, null, null);
        while (cursor.moveToNext()) {
            int idxId = cursor.getColumnIndex(DbSettings.DBEntry._ID);
            int idxUrl = cursor.getColumnIndex(DbSettings.DBEntry.COL_FAV_URL);
            int idxDate = cursor.getColumnIndex(DbSettings.DBEntry.COL_FAV_DATE);
            mFavs.add(new Favourites(cursor.getLong(idxId), cursor.getString(idxUrl), cursor.getLong(idxDate)));
        }
        cursor.close();
        db.close();
    }

    public Favourites addFav(String url, long date) {
        
        Log.d("API123", "addFav " + url);

        SQLiteDatabase db = mFavHelper.getWritableDatabase();
        ContentValues values = new ContentValues();
        values.put(DbSettings.DBEntry.COL_FAV_URL, url);
        values.put(DbSettings.DBEntry.COL_FAV_DATE, date);
        long id = db.insertWithOnConflict(DbSettings.DBEntry.TABLE,
                null,
                values,
                SQLiteDatabase.CONFLICT_REPLACE);
        db.close();
        Favourites fav = new Favourites(id, url, date);
        mFavs.add(fav);
        return new Favourites(fav);
    }

    public void removeFav(long id) {
        SQLiteDatabase db = mFavHelper.getWritableDatabase();
        db.delete(
                DbSettings.DBEntry.TABLE,
                DbSettings.DBEntry._ID + " = ?",
                new String[]{Long.toString(id)}
        );
        db.close();
        
        int index = -1;
        for (int i = 0; i < mFavs.size(); i++) {
            Favourites favourites = mFavs.get(i);
            if (favourites.mId == id) {
                index = i;
            }
        }
        if (index != -1) {
            mFavs.remove(index);
        }
    }

}

در کد بالا ، داده ها را به پایگاه داده SQLite اضافه و از آن حذف یا بارگیری می کنیم.

 

در متد getFavs ما یک کپی عمیق (clone) از ArrayList را انجام می دهیم.

ViewModel نقش مدیر داده برای View های ما را دارد و داده های مورد نیاز را تأمین می کند. متدهای addFav و removeFav در کلاس FavouritesViewModel توسط اکتیویتی برای دو عمل فراخوانی می شوند:

  • برای تغییر در پایگاه داده SQLite
  • برای تغییر داده های ارائه شده به ListView از طریق ArrayList

بنابراین هر بار که View به چیزی نیاز دارد ، ViewModel ما باید دو فراخوانی متد انجام دهد. در آموزش «بکارگیری LiveData در اندروید» که در همین سایت منتشر شده می بینید که چگونه استفاده از LiveData این را بهینه می کند و دو فراخوانی تبدیل به یک فراخوانی می شود.

 

کد مربوط به لایوت activity_main.xml در زیر آورده شده است:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
    android:id="@+id/rlLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ListView
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:src="@android:drawable/ic_input_add"
        android:layout_margin="16dp" />

</RelativeLayout>

 

کد list_item_row.xml در زیر آورده شده است:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="10dp">

    <LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:orientation="vertical">

        <TextView
            android:id="@+id/tvUrl"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:autoLink="web"
            android:padding="8dp"
            android:textColor="@android:color/black"
            android:textSize="20sp" />

        <TextView
            android:id="@+id/tvDate"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    </LinearLayout>

    <ImageButton
        android:id="@+id/btnDelete"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentEnd="true"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:onClick="deleteFav"
        android:src="@android:drawable/ic_menu_delete" />
</RelativeLayout>

 

کد کلاس MainActivity.java در زیر آورده شده است:

package com.journaldev.androidviewmodel;

import android.arch.lifecycle.ViewModelProviders;
import android.content.Context;
import android.content.DialogInterface;
import android.support.annotation.NonNull;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;

import java.util.Date;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    private FavouritesAdapter mFavAdapter;
    private FavouritesViewModel mFavViewModel;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ListView listView = findViewById(R.id.listView);
        FloatingActionButton fab = findViewById(R.id.fab);

        mFavViewModel = ViewModelProviders.of(this).get(FavouritesViewModel.class);

        List<Favourites> favourites = mFavViewModel.getFavs();
        mFavAdapter = new FavouritesAdapter(this, R.layout.list_item_row, favourites);
        listView.setAdapter(mFavAdapter);

        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                final EditText inUrl = new EditText(MainActivity.this);
                AlertDialog dialog = new AlertDialog.Builder(MainActivity.this)
                        .setTitle("New favourite")
                        .setMessage("Add a url link below")
                        .setView(inUrl)
                        .setPositiveButton("Add", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                String url = String.valueOf(inUrl.getText());
                                long date = (new Date()).getTime();
                                // VM AND VIEW
                                mFavAdapter.add(mFavViewModel.addFav(url, date));
                            }
                        })
                        .setNegativeButton("Cancel", null)
                        .create();
                dialog.show();
            }
        });
    }

    public void deleteFav(View view) {
        View parent = (View) view.getParent();
        int position = (int) parent.getTag(R.id.POS);
        Favourites favourites = mFavAdapter.getItem(position);
        mFavViewModel.removeFav(favourites.mId);
        mFavAdapter.remove(favourites);
    }

    public class FavouritesAdapter extends ArrayAdapter<Favourites> {

        private class ViewHolder {
            TextView tvUrl;
            TextView tvDate;
        }

        public FavouritesAdapter(Context context, int layoutResourceId, List<Favourites> todos) {
            super(context, layoutResourceId, todos);
        }

        @Override
        @NonNull
        public View getView(int position, View convertView, ViewGroup parent) {
            Favourites favourites = getItem(position);
            ViewHolder viewHolder;
            if (convertView == null) {
                viewHolder = new ViewHolder();
                LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                convertView = vi.inflate(R.layout.list_item_row, parent, false);
                viewHolder.tvUrl = convertView.findViewById(R.id.tvUrl);
                viewHolder.tvDate = convertView.findViewById(R.id.tvDate);
                convertView.setTag(R.id.VH, viewHolder);
            } else {
                viewHolder = (ViewHolder) convertView.getTag(R.id.VH);

            }

            viewHolder.tvUrl.setText(favourites.mUrl);
            viewHolder.tvDate.setText((new Date(favourites.mDate).toString()));
            convertView.setTag(R.id.POS, position);
            return convertView;
        }

    }
}

در کد بالا ، ما از کلاس ArrayAdapter برای ListView استفاده کرده ایم.

در FloatingActionButton خود ، یک AlertDialog با یک EditText ایجاد می کنیم تا یک URL جدید در ListView خود اضافه کنیم سپس داخل ViewModel آن URL را به SQLite و ArrayList اضافه می کنیم.

برای هر ردیف لیست در XML یک ImageButton تعریف شده است که با کلیک روی آن، آیتم مربوطه از لیست حذف می شود چون ویژگی android: onClick در ImageButton ، متد deleteFav را فراخوانی می کند.

در deleteFav ما دو فراخوانی متد انجام می دهیم - یکی به ViewModel برای حذف رکورد از SQLite و دیگری به ArrayList. این کار باعث هزینه اضافی می شود. در آموزش مربوط به LiveData می بینید که چگونه LiveData این مورد را بهینه می کند. آموزش مربوط به LiveData در مقاله «بکارگیری LiveData در اندروید» در همین سایت منتشر شده است.

کلیک روی tvUrl مستقیماً آدرس را به مرورگر می فرستد برای اینکه ویژگی android:autoLink درtvUrl را برابر true قرار داده ایم:

android:autoLink="true"

 

ما برچسب شناسه (id tag) را به View Holder و view ها در آداپتر ListView اختصاص داده ایم. برچسب های شناسه را در یک فایل tags.xml در پوشه values تعریف کرده ایم:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <item name="VH" type="id" />
    <item name="POS" type="id" />
</resources>

 

 

 

فصلِ: 20 , تعداد قسمت ها: 238 , سطح: صفر تا صد

این فصل در یک نگاه:

فصل رایگان مربوط به مفاهیم php و api نویسی …

توضیحات کلی مجموعه: دوره متخصص اندروید کلیک سایت کامل ترین دوره جامع برنامه نویسی اندروید(حتما دمو دوره را ببینید)   چرا دوره متخصص جایگزین دوره صفرتاصد اندروید شد؟ کلیک سایت تصمیم گرفت …
فصلِ: 30 , تعداد قسمت ها: 182 , سطح: صفر تا صد

این فصل در یک نگاه:

آموزش ساخت اپلیکیشن علی بابا-آموزش کالبک ها-…

دوره "متخصص" جایگزین دوره صفرتاصد اندروید شد. برای دیدن دوره متخصص اندروید بر روی لینک زیر کلیک کنید : https://b2n.ir/d36082 چرا دوره متخصص جایگزین دوره صفرتاصد شده است؟چرا باید دوره متخص…
فصلِ: 11 , تعداد قسمت ها: 121 , سطح: صفر تا صد

این فصل در یک نگاه:

عملیات شبیه فیلتر-ساخت الرت دیالوگ وچیدمان براساس فروش-مرتب سازی-نحوه خطایابی-استفاده از bottom sheet در اندروید-سبد خری…

آموزش ساخت اپلیکیشن اندروید دیجی کالا  : ساخت برنامه اندروید یکی از پر طرفدارترین آموزش های کلیک سایت می باشد. با توجه به فراگیر شدن سیستم اندروید و آشنایی افراد با این سیستم ، برنامه های ک…
فصلِ: 3 , تعداد قسمت ها: 179 , سطح: صفر تا صد

این فصل در یک نگاه:

در این دوره آموزشی ، برنامه نویسی اندروید و ios را با استفاده از زامارین خواهیم آموخت. همچنین به صورت کاملا پروژه محور ، اپلیکیشن فروشگاهی مشابه دیجی کالا را پیاده سازی خواهیم کرد. در انته…
فصلِ: 2 , تعداد قسمت ها: 58 , سطح: صفر تا صد

این فصل در یک نگاه:

توضیحات کلی مجموعه: سرفصل های دوره آموزش ساخت اپلیکیشن فیلیمو معرفی اهداف دوره مقدمه و بررسی پیش نیازهای دوره بررسی جزئی و …
فصلِ: 1 , تعداد قسمت ها: 9 , سطح: صفر تا صد

این فصل در یک نگاه:

آموزش ساخت api key-آموزش استفاده از GPS گوشی ونمایش مکان شخص برروی نقشه-متصل کردن چند نقطه برروی نقشه با خط-رسم چند ضلعی…

حتما دمو دوره رو ببینید اولین دوره کامل کار با نقشه گوگل ومسیریابی در نقشه گوگل(این اموزش مشابه فارسی ندارد) اموزش کار با نقشه گوگل در برنامه نویسی اندروید یکی از مهم ترین مباحث هست که …
فصلِ: 1 , تعداد قسمت ها: 14 , سطح: صفر تا صد

این فصل در یک نگاه:

ساخت انواع نوتیفیکیشن ها -کار با وب سرویس پوشه-ارسال نوتیفیکیشن با سرویس پوشه-ارسال نوتیفیکیشن با one signal-اموزش کار ب…

با این مجموعه همه چیز در مورد نوتیفیکیشن و فایربیس رو خواهید اموخت یکی از مواردی که در استخدام کاربران در شرکت های برنامه نویسی بسیار موثر هست مبحث کار با firebase هست که ما دراین دوره ام…
فصلِ: 1 , تعداد قسمت ها: 16 , سطح: صفر تا صد

این فصل در یک نگاه:

لیست کردن فایل های صوتی ویدیویی گوشی-طاحی متریال وزیبا-استفاده از تب بندی-حرکت سیک بار همراه با اهنگ وزمان-ست کردن زمان …

توضیحات کلی مجموعه: اموزش ساخت یک موزیک پلیر و ویدیو پلیر ح رفه ای که کاملا کاربردی است و قابلیت نصب روی گوشی های مختلف را دارد از جمله امکانات این اپلیکیشن: لیست کردن فایل های صوتی وید…
فصلِ: 1 , تعداد قسمت ها: 61 , سطح: صفر تا صد

این فصل در یک نگاه:

اموزش ساخت اپلیکیشن کافه بازار-اشتراک گذاری اپلیکیشن-کار با رتروفیت-کاربا ران تیم پرمیشن- کار با فرگمنت ها-کار با sqlite…

دوره "متخصص" جایگزین دوره های اندروید شد. برای دیدن دوره متخصص اندروید بر روی لینک زیر کلیک کنید : https://b2n.ir/d36082 چرا دوره متخصص جایگزین دیگر دوره های اندروید شده است؟چرا باید دو…
فصلِ: 1 , تعداد قسمت ها: 9 , سطح: صفر تا صد

این فصل در یک نگاه:

پرداخت درون برنامه ای بازار-اموزش فروش سکه-اموزش فروش اشتراک-اموزش فروش نسخه پولی-اموزش چک کردن خرید کردن کاربر-اموزش کا…

دوره "متخصص" جایگزین دوره های اندروید شد. برای دیدن دوره متخصص اندروید بر روی لینک زیر کلیک کنید : https://b2n.ir/d36082 چرا دوره متخصص جایگزین دیگر دوره های اندروید شده است؟چرا باید دوره…
فصلِ: 1 , تعداد قسمت ها: 20 , سطح: صفر تا صد

این فصل در یک نگاه:

آموزش کامل پیکربندی mvp-اموزش اتصال با سرور با رتروفیت و rxjava-اموزش کار با دیتابیس-آموزش کار با bottom navigation-اموز…

دوره "متخصص" جایگزین دوره های اندروید شد. برای دیدن دوره متخصص اندروید بر روی لینک زیر کلیک کنید : https://b2n.ir/d36082 چرا دوره متخصص جایگزین دیگر دوره های اندروید شده است؟چرا باید دوره…
فصلِ: 1 , تعداد قسمت ها: 35 , سطح: متوسط

این فصل در یک نگاه:

این آموزش در یک فصل شامل 35 جلسه آموزش تصویری به همراه سورس کد ارائه شده است.…

سرفصل ها مقدمه و معرفی متد آموزشی بررسی جزئی و خلاصه موارد موردنیاز پیش از آموزش شامل: کار با ویوها،  کار با کتابخانه های مختلف و ... …
فصلِ: 1 , تعداد قسمت ها: 1 , سطح: صفر تا صد

این فصل در یک نگاه:

آموزش ارسال پیامک با سامانه مدیر پیامک-ارسال کد فعال سازی برنامه با پیامک-اعتبارسنجی کد فعال سازی-ثبت نام در اپلیکیشن با…

دوره "متخصص" جایگزین دوره های اندروید شد. برای دیدن دوره متخصص اندروید بر روی لینک زیر کلیک کنید : https://b2n.ir/d36082 چرا دوره متخصص جایگزین دیگر دوره های اندروید شده است؟چرا باید دوره…
فصلِ: 2 , تعداد قسمت ها: 19 , سطح: صفر تا صد

این فصل در یک نگاه:

آموزش ارسال توکن در اندروید -اموزش امنیت در برنامه نویسی اندروید-اموزش ارسال توکن در هدر در اندروید-اموزش ساخت token -ام…

توضیحات کلی مجموعه: دموی دوره را حتما ببینید دوره امنیت و دیزاین پترن در برنامه نویسی اندروید که شامل دو فصل هست. فصل اول شامل اموزش singletone design patern-builder design patern-command …
فصلِ: 2 , تعداد قسمت ها: 44 , سطح: صفر تا صد

این فصل در یک نگاه:

در فصل دوم این دوره بیشتر میپردازیم به کار با کتابخانه ها و موارد پیشرفته تر مانند دوربین ، ضبط صدا، دیتا بیس ، و .....…

توضیحات کلی مجموعه: سلام خدمت کلیک سایتی های عزیز مجموعه آموزشی صفر تا صد برنامه نویسی اندروید در محیط بیسیک 4 اندروید (basic 4 android) معرفی محیط بیسیک 4 اندروید محیط b4a  تحت کمپانی A…
فصلِ: 3 , تعداد قسمت ها: 61 , سطح: صفر تا صد

این فصل در یک نگاه:

فصل جدید و اپدیت های جدید-آموزش کار با برودکست ریسیور در کاتلین-آموزش چک کردن اتصال به اینترنت در کاتلین-اموزش اپلود کرد…

دوره "متخصص" جایگزین دوره های اندروید شد. برای دیدن دوره متخصص اندروید بر روی لینک زیر کلیک کنید : https://b2n.ir/d36082 چرا دوره متخصص جایگزین دیگر دوره های اندروید شده است؟چرا باید دوره…
فصلِ: 5 , تعداد قسمت ها: 21 , سطح: متوسط

این فصل در یک نگاه:

نحوه ارورگیری-رفع ایراد-رفع مشکل-اشتراک گذاری مطالب-ساخت اکتیویتی تنظیمات-اشتراک گذاری مطالب-جستجو کردن…

دوره "متخصص" جایگزین دوره های اندروید شد. برای دیدن دوره متخصص اندروید بر روی لینک زیر کلیک کنید : https://b2n.ir/d36082 چرا دوره متخصص جایگزین دیگر دوره های اندروید شده است؟چرا باید دوره…
فصلِ: 5 , تعداد قسمت ها: 128 , سطح: صفر تا صد

این فصل در یک نگاه:

پرداخت درون برنامه ای بازار با کاتلین…

دوره "متخصص" جایگزین دوره های اندروید شد. برای دیدن دوره متخصص اندروید بر روی لینک زیر کلیک کنید : https://b2n.ir/d36082 چرا دوره متخصص جایگزین دیگر دوره های اندروید شده است؟چرا باید دوره…
فصلِ: 8 , تعداد قسمت ها: 62 , سطح: صفر تا صد

این فصل در یک نگاه:

اپلود تصاویر روی سرور نود جی اس-کار با کانال در چت- ساخت کانال-ساخت گروه-تفاوت کانال و گروه-انلاین بودن-ارسال تصاویر در …

  توضیحات کلی مجموعه آموزش اندروید اپلیکیشن چت مشابه تلگرام( با استفاده از Socket IO ): دموی مجموعه را حتما ببینید دراین دوره سعی میشود بسیاری از اپشن هایی که اپلیکیشن موبوگرام داراست ر…
فصلِ: 6 , تعداد قسمت ها: 194 , سطح: صفر تا صد

این فصل در یک نگاه:

در این فصل آپدیت های مربوط به دوره را قرار میدهیم…

با سلام و خسته نباشد خدمت کلیک سایتی های عزیز در ادامه با توضیحات مختصری درمورد دوره ی react native با ما همراه باشید: React Native چیست؟ قطعا یکی از آرزوهای برنامه نویسان این میباشد که ب…

تولید شده توسط کلیک سایت

پشتیبانی آنلاین
آماده پاسخگویی هستیم
انتخاب تصویر جهت ارسال:
در حال ضبط صدا

(جهت توقف و یا لغو ضبط از دکمه های زیر استفاده کنید)

توقف و ارسال :
لغو ضبط
در حال حاضر تمامی کارشناسان آفلاین هستند. همواره می توانید با شماره تلگرام / واتساپ 09010005000 به صورت آنلاین با ما در ارتباط باشید. جهت ورود به واتساپ کلیک کنید
0 پیام جدید
پشتیبان در حال تایپ ...
ارسال تصویر ضبط صدا
0 کارشناسان آنلاین می باشند
این گفت و گو توسط پشتیبان به اتمام رسید