تطبيق Flickr بإستعمال Android الجزء الثالت

فهاد الجزء الثالت من تطبيق Flickr بإستعمال Android غادي نكملو ل les classes لي غادي يمكنونا باش نجبدو المعلومات من الرابط لي غادي ناخدوه من موقع Flickr ثم نخزنوهم ومنبعد نعرضوهم فل recyclerView ديالنا.

نظرة سريعة بالفيديو


1- الملف Photo.java


فالمجلد com.example زيد مجلد جديد سميه model فيه زيد ملف جديد عبارة عن java class فيه غادي نخزنو المعلومات الخاصة بالصور فعندنا المعلومات الخاصة بالصور على شكل des variables وهاد لclass كتimplementer لinterface serializable لي كتمكن باش تحول objet لdes bits باش كيسهال ترسلو متبقى كاين غير constructeur ولgetters وsetters الكود ديال الملف هو :

                                    
                                        package com.example.belasri.flickerbrowser.model;

import java.io.Serializable;

/**
 * Created by belasri on 30/04/2017.
 */
public class Photo implements Serializable {
    private static  final long id = 1L;
    private String ItemTitle;
    private String ItemAuthor;
    private String ItemAuthorId;
    private String ItemLink;
    private String ItemTags;
    private String ItemImage;

    public Photo(String itemTitle, String itemAuthor, String itemAuthorId, String itemLink, String itemImage, String itemTags) {
        ItemTitle = itemTitle;
        ItemAuthor = itemAuthor;
        ItemAuthorId = itemAuthorId;
        ItemLink = itemLink;
        ItemImage = itemImage;
        ItemTags = itemTags;
    }
    public String getItemTitle() {
        return ItemTitle;
    }

    public static long getId() {
        return id;
    }

    public String getItemAuthor() {
        return ItemAuthor;
    }

    public String getItemAuthorId() {
        return ItemAuthorId;
    }

    public String getItemLink() {
        return ItemLink;
    }

    public String getItemTags() {
        return ItemTags;
    }

    public String getItemImage() {
        return ItemImage;
    }

    @Override
    public String toString() {
        return "Photo{" +
                "ItemTitle='" + ItemTitle + '\'' +
                ", ItemAuthor='" + ItemAuthor + '\'' +
                ", ItemAuthorId='" + ItemAuthorId + '\'' +
                ", ItemLink='" + ItemLink + '\'' +
                ", ItemTags='" + ItemTags + '\'' +
                ", ItemImage='" + ItemImage + '\'' +
                '}';
    }
}

                                    
                                

2- الملف GetData.java


دائما فالمجلد com.example زيد ملف جديد عبارة عن java class سميه GetData.java فيه غادي يكون الكود لي كيمكن باش نسترجعو المعلومات من الرابط لي غادي نعطيو للclass فهو شوية معقد غادي نحاول نشرحو بالتفصيل فكاين فالأول enum لي كتاخد ل etat ديال téléchargement ديال المعلومات واش نجح ولا فشل ولا مازال ما بدا من بعد كاين des variables لي هما الرابط و data لي هي variable غادي تاخد المعلومات لي استرجعنا من بعد كاين لconstructeur من بعد كاين getter و setter ديال الرابط و data من بعد كاين ل class DownloadStatus لي كت hériter من AsyncTask ولي هي par défaut ديال Android ولي كتمكنا من الإتصال بالرابط ديالنا وتحميل المعلومات منو فمنبعد مكنفتح الconnexion وكنحدد لMethod Get كنسترجع المعلومات وكنخزنها فString Buffer ولي هو بحال أي String منبعد كنسد لconnexion كانت شي erreur كنعرضها الكود ديال الملف هو :

                                    
                                        package com.example.belasri.flickerbrowser;

import android.os.AsyncTask;
import android.util.Log;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * Created by belasri on 30/04/2017.
 */
enum DownloadStatus{IDLE,PROCESSING,NOT_INITIALISED,FAILED_OR_EMPTY,OK}
public class GetData {
    private String LOG_TAG = GetData.class.getSimpleName();
    private String dataUrl;
    private String data;
    private DownloadStatus mDownloadStatus;

    public GetData(String dataUrl) {
        this.dataUrl = dataUrl;
        this.mDownloadStatus = DownloadStatus.IDLE;
    }
    public void setDataUrl(String dataUrl) {
        this.dataUrl = dataUrl;
    }
    public String getData() {
        return data;
    }
    public void execute(){
        mDownloadStatus = DownloadStatus.PROCESSING;
        DownloadData downloadData = new DownloadData();
        downloadData.execute(dataUrl);
    }
    public DownloadStatus getmDownloadStatus() {
        return mDownloadStatus;
    }
    public class DownloadData extends AsyncTask<String, Void, String>{
        @Override
        protected void onPostExecute(String dataReturned) {
            data = dataReturned;
            Log.v(LOG_TAG,"Data returned :" + dataReturned);
            if(dataReturned == null){
                if(dataUrl == null){
                    mDownloadStatus = DownloadStatus.NOT_INITIALISED;
                }else{
                    mDownloadStatus = DownloadStatus.FAILED_OR_EMPTY;
                }
            }else{
                //success
                mDownloadStatus = DownloadStatus.OK;
            }
        }

        @Override
        protected String doInBackground(String... params) {
            HttpURLConnection connection = null;
            BufferedReader reader = null;
            if(params == null) {
                return null;
            }
            try{
                URL url = new URL(params[0]);
                connection = (HttpURLConnection) url.openConnection();
                connection.setRequestMethod("GET");
                connection.connect();
                InputStream input = connection.getInputStream();
                if(input == null){
                    return null;
                }
                StringBuffer buffer = new StringBuffer();
                reader = new BufferedReader(new InputStreamReader(input));
                String line;
                while((line = reader.readLine()) != null){
                    buffer.append(line + "\n");
                }
                return  buffer.toString();
            }catch (IOException e){
                Log.e(LOG_TAG,e.getMessage());
                return null;
            }finally {
                if(connection != null){
                    connection.disconnect();
                }
                if(reader != null){
                    try{
                        reader.close();
                    }catch(IOException e){
                        Log.e(LOG_TAG,e.getMessage());
                    }
                }
            }
        }
    }
 }

                                    
                                

3- الملف GetFlickerDataInJson.java


دائما فالمجلد com.example زيد ملف جديد عبارة عن java class سميه GetFlickerDataInJson.java ولي كت hériter من الملف لي زدنا من قبل GetData وفيه des variables لي هما الرابط وList ديال les photos ديالنا فكل objet استرجعناه غادي يكون عبارة عن صورة من بعد غادي نخزنوها فهاد List منبعد كاين ل constructeur لي كينفد fonction createSuitbaleUri لي كتاخد tag لي هي الحاجة لي كنبحثو عليها ول paramétre الثاني هو خاص بلApi باش تعرف كل les paramétres لي كياخدهم الرابط شوف الرابط من هنا https://www.flickr.com/services/feeds/docs/photos_public منبعد كاين fonction createSuitbaleUri لي كترجعنا الرابط منبعد مكتزيدلو كل les paramétres فالرابط غادي يكون على هاد الشكل https://api.flickr.com/services/feeds/photos_public.gne?tags=android&lang=fr&format=json&nojsoncallback=1 من بعد كاين DownloadJsonData لي هي class كت hériter من DownloadData لي كاينة فل class GetData فكتعطيها الرابط من بعد كتخد المعلومات لي رجعت وكتنفد لfonction readResult لي كتسترجع المعلومات من الرابط على شكل json وكت créer objet من la class photo وكتعطيه المعلومات لي جبدت ومنبعد كتزيد لobjet فList أما لfonction execute فهي كت EXECUTER ل class DownloadData لي كاينة ف GetData وهاد ل fonction غادي نخدمو بها فل class MainActivity وهي فالحقيقة ماشي fonction هي procedure حيت غير كتنفد الكود ومكت retourner والو الكود ديال الملف هو :

                                      
                                        package com.example.belasri.flickerbrowser;

import android.net.Uri;
import android.util.Log;

import com.example.belasri.flickerbrowser.model.Photo;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

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

/**
 * Created by belasri on 30/04/2017.
 */
public class GetFlickerDataInJson extends GetData {
    private  String LOG_TAG = GetFlickerDataInJson.class.getSimpleName();
    private List<Photo> mPhotos;
    private Uri destinationUrl;
    public GetFlickerDataInJson(String searchingTag,Boolean MatchAll) {
        super(null);
        createSuitbaleUri(searchingTag,MatchAll);
        mPhotos = new ArrayList<Photo>();
    }
    private boolean createSuitbaleUri(String searchingTag, Boolean matchAll) {
        final String Flicker_Base_Url = "https://api.flickr.com/services/feeds/photos_public.gne";
        final String TAGS_PARAM = "tags";
        final String TAGMODE_PARAM = "tagmode";
        final String FORMAT_PARAM = "format";
        final String LANG = "lang";
        final String NO_JSON_CALLBACK__PARAM = "nojsoncallback";
        destinationUrl = Uri.parse(Flicker_Base_Url).buildUpon()
                .appendQueryParameter(TAGS_PARAM,searchingTag)
                .appendQueryParameter(TAGMODE_PARAM,matchAll ? "ALL" : "ANY")
                .appendQueryParameter(FORMAT_PARAM,"json")
                .appendQueryParameter(LANG,"fr")
                .appendQueryParameter(NO_JSON_CALLBACK__PARAM,"1")
                .build();
        return destinationUrl != null;
    }
    public class DownloadJsonData extends DownloadData{
        @Override
        protected void onPostExecute(String dataReturned) {
            super.onPostExecute(dataReturned);
            readResult();
        }

        @Override
        protected String doInBackground(String... params) {
            String[] param = {destinationUrl.toString()};
            return super.doInBackground(param);
        }
    }
    public List<Photo> getmPhotos() {
        return mPhotos;
    }
    public void execute(){
        super.setDataUrl(destinationUrl.toString());
        DownloadJsonData downloadData = new DownloadJsonData();
        Log.e(LOG_TAG,"Built url :" + destinationUrl);
        downloadData.execute(destinationUrl.toString());
    }
    private void readResult() {
        if(getmDownloadStatus() != DownloadStatus.OK){
            Log.e(LOG_TAG,"Error while downloading data");
            return;
        }
        final String DATA_ITEMS = "items";
        final String DATA_TITLE = "title";
        final String DATA_MEDIA = "media";
        final String DATA_PHOTO_URL = "m";
        final String DATA_AUTHOR = "author";
        final String DATA_AUTHOR_ID = "author_id";
        final String DATA_LINK = "link";
        final String DATA_TAGS = "tags";
        try{
            JSONObject jsonData = new JSONObject(getData());
            JSONArray jsonItemsArray = jsonData.getJSONArray(DATA_ITEMS);
            for(int i=0;i<jsonItemsArray.length();i++){
                JSONObject jsonPhoto = jsonItemsArray.getJSONObject(i);
                String title = jsonPhoto.getString(DATA_TITLE);
                String author = jsonPhoto.getString(DATA_AUTHOR);
                String authorId = jsonPhoto.getString(DATA_AUTHOR_ID);
                String link = jsonPhoto.getString(DATA_LINK);
                String tags = jsonPhoto.getString(DATA_TAGS);
                JSONObject photoMedia = jsonPhoto.getJSONObject(DATA_MEDIA);
                String photoUrl = photoMedia.getString(DATA_PHOTO_URL);
                Photo photoObject = new Photo(title,author,authorId,link,photoUrl,tags);
                this.mPhotos.add(photoObject);
            }
            for(Photo photoObject : mPhotos){
                Log.e(LOG_TAG,photoObject.toString());
            }
        }catch(JSONException ex){
            ex.printStackTrace();
            Log.e(LOG_TAG,"Error getting json data");
        }
    }
}

                                      
                                    

4- الملف FlickerImageHolder.java


دائما فالمجلد com.example زيد مجلد جديد سميه adapters زيد فيه ملف جديد عبارة عن java class سميه FlickerImageHolder.java هاد لي غادي يمكنا باش نزيدو الملف لي كنا زدنا photo_list_item.xml ولي هو عنصر من recyclerview ف recyclerview الكود ديال الملف هو :

                                        
                                            package com.example.belasri.flickerbrowser.adapters;

import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;

import com.example.belasri.flickerbrowser.R;

/**
 * Created by belasri on 01/05/2017.
 */
public class FlickerImageHolder extends RecyclerView.ViewHolder {
    protected ImageView thumbnail;
    protected TextView title;
    public FlickerImageHolder(View view) {
        super(view);
        this.title = (TextView) view.findViewById(R.id.title);
        this.thumbnail = (ImageView) view.findViewById(R.id.thumbnail);
    }
}
                                        
                                    

5- الملف FlickerRecyclerViewAdapter.java


دائما فالمجلد adapters زيد فيه ملف جديد عبارة عن java class سميه FlickerRecyclerViewAdapter.java هاد لclass لي كتستقبل liste ديال les objets ديالنا لي type ديالهم Photo من بعد مكيتزادو العناصر فrecyclerview بواسطة FlickerImageHolder منبعد كيزيد الصورة لي كاينة فل objet photo ف ImageView بواسطة Picasso والعنوان كيزيدو ف TextView ومتبقى هادوك des fonctions لي لازم متimplementer لي كيرجعو عدد الصور لي كاينين ف List وصورة فposition معينة الكود ديال الملف هو :

                                        
                                            package com.example.belasri.flickerbrowser.adapters;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.example.belasri.flickerbrowser.R;
import com.example.belasri.flickerbrowser.model.Photo;
import com.squareup.picasso.Picasso;

import java.util.List;

/**
 * Created by belasri on 01/05/2017.
 */
public class FlickerRecyclerViewAdapter extends RecyclerView.Adapter<FlickerImageHolder>{
    private List<Photo> mPhotoList;
    private Context context;
    public FlickerRecyclerViewAdapter(Context context,List<Photo> photoList) {
        this.context = context;
        this.mPhotoList = photoList;
    }
    @Override
    public FlickerImageHolder onCreateViewHolder(ViewGroup parent, int i) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.photo_list_item,null);
        FlickerImageHolder flickerImageHolder = new FlickerImageHolder(view);
        return flickerImageHolder;
    }
    @Override
    public void onBindViewHolder(FlickerImageHolder holder, int position) {
        Photo photo = mPhotoList.get(position);
        Picasso.with(context).load(photo.getItemImage())
                .error(R.drawable.placeholder)
                .placeholder(R.drawable.placeholder)
                .into(holder.thumbnail);
        holder.title.setText(photo.getItemTitle());
    }
    @Override
    public int getItemCount() {
        return (null != mPhotoList ? mPhotoList.size() : 0);
    }
    public Photo getPhoto(int position){
        return (mPhotoList != null) ? mPhotoList.get(position) : null;
    }
}

                                        
                                    

كلمات مفاتيح :