آموزش CardView و Mysql در برنامه نویسی اندروید
سلام دوستان امیدوارم حالتون خوب باشد در این سری از آموزش برنامه نویسی اندروید به آموزش CardView و Mysql در برنامه نویسی اندروید می پردازیم در این آموزش داده های ما در دیتابیس mysql قرار می گیرند سپس با استفاده از فایل php این داده ها خوانده می شوند و به json تبدیل می شوند سپس در برنامه قرار می گیرد در ادامه می توانید پیش نمایشی از آن را مشاهده کنید با ما همراه باشید.
ابتدا ما به یک دیتابیس نیاز داریم وارد سرور خود شده یک دیتابیس ایجاد کرده یا در xammp (مجازی ساز ویندوزی) این کار را انجام دهید. در دیتابیس ساخته شده یک جدول به نام my_data با سه فیلد به نام های id , description , image ایجاد کرده و id را برابر با Primary key قرار دهید در آن چند Insert انجام دهید حتما در بخش Image باید آدرس عکس باشد و id هم باید منحصر به فرد باشد و پشت سرهم (یعنی 1 و 2 و 3 و…) و در بخش description یک متن تست قرار دهید از عکس زیر هم می توانید استفاده کنید.
lما 4 داده تست در آن ها Insert کرده ایم.
بعد از اینکه دیتابیس را جدول و فیلدهای ایجاد کردید یک فایل php به نام script.php در سرور یا در local مربوط به xampp (پوشه htdocs) ایجاد کرده و کدهای زیر را در آن قرار دهید.
1 2 3 4 5 6 7 8 9 10 11 | <?php $connection = mysqli_connect("localhost","my_user","my_password","my_db"); $id = $_GET["id"]; $query = "Select * from my_data where id between ($id+1) and ($id+4)"; $result = mysqli_query($connection,$query); while ($row = mysqli_fetch_assoc($result)) { $array[] = $row; } header('Content-Type:Application/json'); echo json_encode($array); ?> |
شما باید در بالا فیلد mysqli_connect را تغییر دهید (localhost را تغییر ندهید ) باید به جای my_user یوزر دیتابیستون و به جای my_password پسوردی که برای یوزر گذاشتید و به جای my_db نام دیتابیس را قرار دهید (نام جدول نیست !)
کد بالا داده ها را از دیتابیس خونده و به صورت json نمایش می دهد.
در این آموزش ما با چهار کتاب خانه کار خواهیم کرد که عبارتند از :
- okhttp
- cardview
- recyclerview
- glide
ابتدا وارد فایل Build.gradle از نوع Module شده سپس در بخش dependencies خط های زیر اضافه کنید.
1 2 3 4 | compile 'com.squareup.okhttp3:okhttp:3.2.0' compile 'com.android.support:cardview-v7:24.0.+' compile 'com.android.support:recyclerview-v7:24.0.+' compile 'com.github.bumptech.glide:glide:3.7.0' |
پروژه را sync کنید.
وارد فایل AndriodManifest.xml شده و دسترسی زیر را اضافه کنید.
1 | <uses-permission android:name="android.permission.INTERNET"/> |
در پوشه layout یک فایل به نام card.xml ایجاد کرده و کدهای زیر را در آن قرار دهید.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:card_view="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content"> <android.support.v7.widget.CardView android:id="@+id/card_view" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="center" android:elevation="3dp" card_view:cardUseCompatPadding="true" card_view:cardElevation="4dp" card_view:cardCornerRadius="1dp" > <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:id="@+id/image" android:layout_width="match_parent" android:layout_height="100dp" android:background="?attr/selectableItemBackgroundBorderless" android:clickable="true" android:scaleType="centerCrop" /> <TextView android:id="@+id/description" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/image" android:paddingLeft="5dp" android:paddingRight="5dp" android:paddingTop="5dp" android:textColor="@color/cardview_dark_background" android:text="test" android:textSize="12sp" android:textStyle="normal" android:typeface="sans" /> </RelativeLayout> </android.support.v7.widget.CardView> </LinearLayout> |
در بالا شکل ظاهری هر آیتم ایجاد شده است که در ادامه از آن استفاده می کنیم و آن را در layout اصلی Inflate می کنیم.
و باید در layout اصلی که نام آن برابر با activity_main.xml کد زیر را قرار دهید.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <?xml version="1.0" encoding="utf-8"?> <RelativeLayout android:layout_width="wrap_content" android:layout_height="wrap_content" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:card_view="http://schemas.android.com/tools"> <android.support.v7.widget.RecyclerView android:id="@+id/recycler_view" android:layout_width="match_parent" android:layout_height="wrap_content" card_view:cardUseCompatPadding="true" card_view:cardElevation="5dp" card_view:cardCornerRadius="5dp" android:scrollbars="vertical" android:layout_marginLeft="6dp" android:layout_marginRight="6dp" android:layout_marginTop="6dp" /> </RelativeLayout> |
در بالا یک RecyclerView قرار داده شده است تا card.xml در آن Render شود.
حالا باید یک فایل به نام CustomAdapter.java ایجاد کرده و کدهای زیر را در آن قرار دهید این همان آداپتور سفارشی ما است.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | package ir.programchi; import android.content.Context; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; import com.bumptech.glide.Glide; import java.util.List; /** * Created by Jefferson on 9/16/2016. */ public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.ViewHolder> { private Context context; private List<MyData> my_data; public CustomAdapter(Context context, List<MyData> my_data) { this.context = context; this.my_data = my_data; } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.card,parent,false); return new ViewHolder(itemView); } @Override public void onBindViewHolder(ViewHolder holder, int position) { holder.description.setText(my_data.get(position).getDescription()); Glide.with(context).load(my_data.get(position).getImage_link()).into(holder.imageView); } @Override public int getItemCount() { return my_data.size(); } public class ViewHolder extends RecyclerView.ViewHolder{ public TextView description; public ImageView imageView; public ViewHolder(View itemView) { super(itemView); description = (TextView) itemView.findViewById(R.id.description); imageView = (ImageView) itemView.findViewById(R.id.image); } } } |
کد بالا همان getter و setter است .
بعد از اینکه آداپتور را ایجاد کردید یک کلاس جاوا به نام MyData.java ایجاد کرده و کدهای زیر را در آن قرار دهید.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | package ir.programchi; /** * Created by Jefferson on 9/16/2016. */ public class MyData { private int id; private String description,image_link; public MyData(int id, String description, String image_link) { this.id = id; this.description = description; this.image_link = image_link; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public String getImage_link() { return image_link; } public void setImage_link(String image_link) { this.image_link = image_link; } } |
این کلاس هم باز getter و setter است ولی برای json ما که از سرور دریافت می شود.
و در آخر باید وارد اکتویتی اصلی که در اینجا نام آن برابر با MainActivity.java است کدهای زیر را قرار دهید.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | package ir.programchi; import android.os.AsyncTask; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.RecyclerView; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.io.IOException; import java.util.ArrayList; import java.util.List; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; public class MainActivity extends AppCompatActivity { private RecyclerView recyclerView; private GridLayoutManager gridLayoutManager; private CustomAdapter adapter; private List<MyData> data_list; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); recyclerView = (RecyclerView) findViewById(R.id.recycler_view); data_list = new ArrayList<>(); load_data_from_server(0); gridLayoutManager = new GridLayoutManager(this,2); recyclerView.setLayoutManager(gridLayoutManager); adapter = new CustomAdapter(this,data_list); recyclerView.setAdapter(adapter); recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { if(gridLayoutManager.findLastCompletelyVisibleItemPosition() == data_list.size()-1){ load_data_from_server(data_list.get(data_list.size()-1).getId()); } } }); } private void load_data_from_server(int id) { AsyncTask<Integer,Void,Void> task = new AsyncTask<Integer, Void, Void>() { @Override protected Void doInBackground(Integer... integers) { OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder() .url("https://programchi.ir/script.php?id="+integers[0]) .build(); try { Response response = client.newCall(request).execute(); JSONArray array = new JSONArray(response.body().string()); for (int i=0; i<array.length(); i++){ JSONObject object = array.getJSONObject(i); MyData data = new MyData(object.getInt("id"),object.getString("description"), object.getString("image")); data_list.add(data); } } catch (IOException e) { e.printStackTrace(); } catch (JSONException e) { System.out.println("End of content"); } return null; } @Override protected void onPostExecute(Void aVoid) { adapter.notifyDataSetChanged(); } }; task.execute(id); } } |
در بالا به سرور reuqst ارسال می شود تا داده ها دریافت شود بر اساس هر آیدی داده دریافت شده و در Card قرار می گیرد برای انجام request از okhttp استفاده شده است دفت کنید باید در کد بالا خط زیر را تغییر دهید.
1 | https://programchi.ir/script.php |
دقت کنید فقط همین بخش بقیه را نباید تغییر دهید در اینجا از کلاس Async Task استفاده کردیم تا عملیات در Background انجام شود. برای اینکه به شکل دوتایی در کنار هم قرار گیرند از GridLayoutManager استفاده کردیم (قبلا آموزشش را قرار داده بودیم)
این آموزش هم به پایان رسید.
موفق و پیروز باشید.
سلام. من طبق آموزش شما پیش رفتم ولی خطای زیر به من نشون داده میشه و صفحه اپلیکیشن یه صفحه سفید بدون حتی اکشن بار میشه
10-27 09:51:14.743 562-826/system_process I/ActivityManager: START u0 {act=android.intent.action.DELETE dat=package:app.my.project flg=0x10800000 cmp=com.android.packageinstaller/.UninstallerActivity} from pid 1613
10-27 09:51:17.239 562-579/system_process I/ActivityManager: Force stopping package app.my.project appid=10052 user=-1
10-27 09:51:17.243 562-597/system_process W/PackageManager: Couldn’t delete native library directory /data/app-lib/app.my.project
10-27 09:51:17.263 562-597/system_process I/ActivityManager: Force stopping package app.my.project appid=10052 user=0
10-27 09:51:17.295 562-575/system_process D/BackupManagerService: Received broadcast Intent { act=android.intent.action.PACKAGE_REMOVED dat=package:app.my.project flg=0x8000010 (has extras) }
10-27 09:51:17.323 804-31659/android.process.acore D/VoicemailCleanupService: Cleaning up data for package: app.my.project
10-27 09:51:27.507 562-597/system_process W/ActivityManager: No content provider found for permission revoke: file:///data/local/tmp/app.my.project
10-27 09:51:27.507 562-597/system_process W/ActivityManager: No content provider found for permission revoke: file:///data/local/tmp/app.my.project
10-27 09:51:27.671 562-597/system_process I/PackageManager: Running dexopt on: app.my.project
10-27 09:51:27.947 562-579/system_process I/ActivityManager: Force stopping package app.my.project appid=10052 user=-1
10-27 09:51:27.983 562-575/system_process D/BackupManagerService: Received broadcast Intent { act=android.intent.action.PACKAGE_ADDED dat=package:app.my.project flg=0x8000010 (has extras) }
10-27 09:51:28.471 562-1240/system_process I/ActivityManager: START u0 {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=app.my.project/.MainActivity} from pid 31690
10-27 09:51:28.547 562-1236/system_process I/ActivityManager: Start proc app.my.project for activity app.my.project/.MainActivity: pid=31700 uid=10052 gids={50052, 3003, 1028}
10-27 09:51:29.835 31700-31700/app.my.project W/EGL_genymotion: eglSurfaceAttrib not implemented
10-27 09:51:29.835 31700-31700/app.my.project E/OpenGLRenderer: Getting MAX_TEXTURE_SIZE from GradienCache
10-27 09:51:29.915 31700-31700/app.my.project E/OpenGLRenderer: Getting MAX_TEXTURE_SIZE from Caches::initConstraints()
10-27 09:51:29.919 31700-31700/app.my.project D/OpenGLRenderer: Enabling debug mode 0
10-27 09:51:29.919 31700-31700/app.my.project I/Choreographer: Skipped 73 frames! The application may be doing too much work on its main thread.
10-27 09:51:30.755 562-578/system_process I/ActivityManager: Displayed app.my.project/.MainActivity: +2s215ms
لطفا راهنمایی کنید.
با تشکر
سلام خطای اصلی را قرار دهید این بخش غیر قابل تفسیر است.
درود
با عرض خسته نباشید
من این پروژه رو هرجور و هر کاری کردم به مشکل برخوردم وقتی اجراش هم کردم کار نکرد لطفا اگر امکانش هست فایل نهایی که پروژه تکمیل میشه رو برام ایمیل کنید با تشکر
سلام و درود
دوست عزیز ابتدا به صورت debug جلو برید و بررسی کنید که در چه بخشی به خطا می خورید و امکان ارسال یا قرار دادن سورس وجود ندارد url که فرستادید رو بررسی کردم مشکلی نداشته و json به درستی ایجاد شده است مطمئنن در بخش pasrse جیسون مشکل دارید logcat قرار دهید تا بررسی کنیم
موفق باشید.
اینم فایل script من
masalro.ir/script.php
درود و خسته نباشید چیشد؟
با سلام و خسته نباشید خدمت شما
اول از هر چیز خواستم از زحمات شما تشکر کنم
من این برنامه را نوشتم و از سرور مجازی xampp استفاده می کنم.
همه چیز درسته و برنامه اجرا میشه و cardView به اندازه رکوردهای ثبت شده من در دیتابیس (که 3 رکورد هست) نمایش داده میشه
اطلاعات url عکس هم از طریق json وارد برنامه میشه ( توسط Toast خروجی گرفتم و آدرس url عکس به درستی نشون داده شد)
ولی مشکلی که دارم عکس های مربوطه در cardView نشون داده نمیشه و در خروجی برنامه سه card خالی به من نشون میده.
خواستم دلیلشو بدونم برنامه مشکلی داره یا به خاطر اینکه از سرور مجازی استفاده می کنم cardView نمی تونه عکسها رو load کنه
با تشکر
سلام و درود چک کنید دسترسی اینترنت را قرار داده باشید و کدها را با استفاده از layout inspector چک کنید که آیا واقعا عکس ها لود نمیشه یا خیر.
موفق باشید.