آموزش پارس Json + قرار دادن در RecyclerView

امتیاز 5.00 ( 1 رای )

سلام دوستان در این سری از آموزش برنامه نویسی اندروید به آموزش پارس Json + قرار دادن در RecyclerView می پردازیم منظور از پارس (parse) تجزیه است. در ادامه خواهید دید که به چه شکل زیبای نمایش داده خواهد شد (سعی کردیم شبیه به بخش فروشگاه دیجی کالا باشد) در این آموزش از کتاب خانه قدرتمند Retrofit برای بخش پارس json استفاده می کنیم در ادامه می توانید پیش نمایشی از آن را مشاهده کنید با ما همراه باشید..

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

  • Android Retrofit
  • GSON Converter
  • RecyclerView
  • CardView
  • Universal Image Loader

در ابتدای کار باید وارد فایل Build.gradle از نوع module شده و در بخش dependencies خط های زیر را اضافه کنید.

    compile 'com.squareup.retrofit2:retrofit:2.2.0'
    compile 'com.squareup.retrofit2:converter-gson:2.2.0'
    compile 'com.android.support:recyclerview-v7:25.1.1'
    compile 'com.android.support:cardview-v7:25.1.1'
    compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.5'

سپس پروژه را sync کنید کمی بیشتر از حد معمول طول می کشد چون تعداد کتاب خانه ها زیاد است . علت خطاهای احتمالی گریدل را قبلا بررسی کرده ایم در سایت واژه “gradle” را جستجو کنید.
بعد از sync شدن پروژه وارد فایل AndroidManifest.xml شده و دسترسی زیر را اضافه کنید.

<uses-permission android:name="android.permission.INTERNET"></uses-permission>

حالا وارد layout خود شده در اینجا نام آن برابر با  activity_main.xml است و کد های زیر را در آن قرار دهید.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity">
    <android.support.v7.widget.RecyclerView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/recycle"
        >
    </android.support.v7.widget.RecyclerView>
</RelativeLayout>

همانطور که مشاهده می کنید یک RecyclerView در layout اصلی قرار داده ایم.
حالا باید یک فایل به نام list.xml ایجاد کرده و کدهای زیر را در آن قرار دهید.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:background="#ffffff">
    <android.support.v7.widget.CardView
        android:id="@+id/card_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_margin="@dimen/card_margin"
        android:elevation="3dp"
        card_view:cardCornerRadius="@dimen/card_album_radius">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="16dp"
        android:orientation="vertical"
        android:gravity="center">
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="16dp"
            android:orientation="vertical"
            android:gravity="center">
            <ImageView
                android:id="@+id/productimage"
                android:layout_width="150dp"
                android:layout_height="150dp"
                android:src="@mipmap/ic_launcher"
                android:gravity="center"
                />
            <LinearLayout
                android:layout_weight="0.1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="vertical"
                android:layout_marginTop="10dp"
                >
                <TextView
                    android:id="@+id/price"
                    android:maxLines="2"
                    android:textSize="20dp"
                    android:layout_width="wrap_content"
                    android:layout_height="match_parent"
                    android:text="INR 0000"
                    android:textColor="#000000"
                    />
                <TextView
                    android:id="@+id/name"
                    android:textSize="15dp"
                    android:layout_width="wrap_content"
                    android:layout_height="match_parent"
                    android:text="Wrist Watches"
                    android:layout_marginTop="7dp"
                    android:textColor="#000000"
                    />
                <TextView
                    android:id="@+id/color"
                    android:textSize="13dp"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="RED"
                    android:layout_marginTop="7dp"
                    android:textColor="#000000"
                    />
           </LinearLayout>
        </LinearLayout>
    </LinearLayout>
    </android.support.v7.widget.CardView>
</LinearLayout>

شاید بپرسید این کدام بخش از کار است . کد بالا در RecyclerView ما render یا بارگذاری می شود که شامل CardView  و عکس ها و Text ها می شود .
حلا باید یک InterFace به نام ApiService.java با annotation (تفسیر) “@GET” برای دریافت Response ایجاد کرده همانند زیر

package ir.programchi;
import java.util.List;
import retrofit2.Call;
import retrofit2.http.GET;
/**
 * Created by JFP on 01-May-17.
 */
public interface APiService {
    @GET("/api/product.php")
    Call<List<Product>> getbookdetails();
}

در بالا /api/product.php بخشی از مسیر json ما است. نباید در آن http قرار دهید.
مسیر فایل json در هاست ما

orjinakteb.com/api/product.php

حالا باید getter و setter خودمان را ایجاد کنیم پس یک فایل به نام  Product.java ایجاد کرده و کدهای زیر را در آن قرار دهید.

package ir.programchi;
/**
 * Created by JFP on 01-May-17.
 */
public class Product {
    int productid;
    String productname;
    String price;
    String instock;
    String offer;
    String color;
    String imageurl;
    public int getProductid() {
        return productid;
    }
    public void setProductid(int productid) {
        this.productid = productid;
    }
    public String getProductname() {
        return productname;
    }
    public void setProductname(String productname) {
        this.productname = productname;
    }
    public String getPrice() {
        return price;
    }
    public void setPrice(String price) {
        this.price = price;
    }
    public String getInstock() {
        return instock;
    }
    public void setInstock(String instock) {
        this.instock = instock;
    }
    public String getOffer() {
        return offer;
    }
    public void setOffer(String offer) {
        this.offer = offer;
    }
    public String getColor() {
        return color;
    }
    public void setColor(String color) {
        this.color = color;
    }
    public String getImageurl() {
        return imageurl;
    }
    public void setImageurl(String imageurl) {
        this.imageurl = imageurl;
    }
}

زمان آن رسیده که آداپتور مربوط به RecyclerView ایجاد کنیم پس یک فایل به نام  Recycleradapter.java ایجاد کرده و کدهای زیر را در آن قرار دهید.

package ir.programchi;
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.nostra13.universalimageloader.core.ImageLoader;
import java.util.List;
/**
 * Created by JFP on 01-May-17.
 */
public class Recycleradapter extends RecyclerView.Adapter<Recycleradapter.MyHolder>{
    List<Product> list;
    ImageLoader imageLoader;
    public Recycleradapter(List<Product> list, ImageLoader imageLoader) {
        this.list = list;
        this.imageLoader=imageLoader;
    }
    @Override
    public MyHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list,parent,false);
        MyHolder myHolder = new MyHolder(view);
        return myHolder;
    }
    @Override
    public void onBindViewHolder(MyHolder holder, int position) {
        Product product = list.get(position);
        holder.name.setText(product.getProductname());
        holder.color.setText(product.getColor());
        String image1 = product.getImageurl();
        imageLoader.displayImage(image1, holder.image);
        holder.price.setText("INR "+product.getPrice());
    }
    @Override
    public int getItemCount() {
        return list.size();
    }
    class MyHolder extends RecyclerView.ViewHolder{
          TextView name, color,price;
        ImageView image;
        public MyHolder(View itemView) {
            super(itemView);
            image= (ImageView) itemView.findViewById(R.id.productimage);
            name = (TextView) itemView.findViewById(R.id.name);
            color = (TextView) itemView.findViewById(R.id.color);
            price= (TextView) itemView.findViewById(R.id.price);
        }
    }
}

 
قبلا هم چندین بار این کلاس را توضیح داده بودیم ولی یک اشاره کوچک به آن خواهیم کرد ابتدا layout که درست کردیم اگر یادتان باشد اسم آن برابر با list بود باید آن را Inflate کنیم بعد از آن زمان آن است که مقدار های را در Textview ها قرار دهیم فقط TexTview نیست ImageView و بیقه اجزا نیز هستند باید تعداد card های که می خواهند درآنها TextView و Image View و.. قرار بگیرد به دست بیاید.
و در آخر باید کد زیر را در MainActivity.java قرار دهید.

package ir.programchi;
import android.content.res.Resources;
import android.graphics.Rect;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.TypedValue;
import android.view.View;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
import java.util.ArrayList;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class MainActivity extends AppCompatActivity {
    RecyclerView recyclerView;
    List<Product> listing;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        recyclerView = (RecyclerView) findViewById(R.id.recycle);
        ImageLoaderConfiguration config=new ImageLoaderConfiguration.Builder(this).build();
        ImageLoader.getInstance().init(config);
        listing = new ArrayList<>();
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://orjinakteb.com")
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        APiService service = retrofit.create(APiService.class);
                    Call<List<Product>> call=   service.getbookdetails();
          call.enqueue(new Callback<List<Product>>() {
              @Override
              public void onResponse(Call<List<Product>> call, Response<List<Product>> response) {
                  List<Product> list = response.body();
                  Product product = null;
                  for (int i =0 ;i<list.size();i++){
                      product = new Product();
                      String name = list.get(i).getProductname();
                      String color = list.get(i).getColor();
                      String image = list.get(i).getImageurl();
                      String price = list.get(i).getPrice();
                      product.setPrice(price);
                      product.setColor(color);
                      product.setProductname(name);
                      product.setImageurl(image);
                      listing.add(product);
                  }
                  Recycleradapter recyclerAdapter = new Recycleradapter(listing,ImageLoader.getInstance());
                  RecyclerView.LayoutManager recyce = new GridLayoutManager(MainActivity.this,2);
                  recyclerView.addItemDecoration(new GridSpacingdecoration(2, dpToPx(10), true));
                  recyclerView.setLayoutManager(recyce);
                  recyclerView.setItemAnimator( new DefaultItemAnimator());
                  recyclerView.setAdapter(recyclerAdapter);
              }
              @Override
              public void onFailure(Call<List<Product>> call, Throwable t) {
              }
          });
    }
    public class GridSpacingdecoration extends RecyclerView.ItemDecoration {
        private int span;
        private int space;
        private boolean include;
        public GridSpacingdecoration(int span, int space, boolean include) {
            this.span = span;
            this.space = space;
            this.include = include;
        }
        @Override
        public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
            int position = parent.getChildAdapterPosition(view);
            int column = position % span;
            if (include) {
                outRect.left = space - column * space / span;
                outRect.right = (column + 1) * space / span;
                if (position < span) {
                    outRect.top = space;
                }
                outRect.bottom = space;
            } else {
                outRect.left = column * space / span;
                outRect.right = space - (column + 1) * space / span;
                if (position >= span) {
                    outRect.top = space;
                }
            }
        }
    }
    /**
     * Converting dp to pixel
     */
    private int dpToPx(int dp) {
        Resources r = getResources();
        return Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, r.getDisplayMetrics()));
    }
}

برای اینکه به شکل دوتایی بقل هم نمایش پیدا کنند از LayoutManager استفاده شده است همانطور که در ابتدای کد دید از Retrofit برای دریافت json استفاده شده است و در قبل هم اشاره کرده که ادرس json باید به صورت  خاص به retrofit داده یا feed شود برای اینکه دوتای به صورت دقیق در کنار هم قرار گیرند ما اندازه صفحه به pixel به دست آوردیم سپس از فاصله هر ستون کم کردیم و در آخر آن را قرار داده ایم.
 
 
این آموزش هم به پایان رسید.
 
موفق و موید باشید.
 
 

مطالعه بیشتر