28 Şubat 2018 Çarşamba

Android - LightingColorFilter example and BitmapShader example, how to change BitmapShader color

Paint drawPaint;
drawPaint = new Paint(); 

drawPaint.setColor(paintColor);

drawPaint.setAntiAlias(true);
drawPaint.setStrokeWidth(brushSize);
drawPaint.setStyle(Paint.Style.STROKE);
drawPaint.setStrokeJoin(Paint.Join.ROUND);
drawPaint.setStrokeCap(Paint.Cap.ROUND);


drawPaint.setShader(new BitmapShader(shaderBitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT));
ColorFilter filter = new LightingColorFilter(paintColor , 0x00000000 );
drawPaint.setColorFilter(filter);
Output :

--------------------------------------------------------------------------------------
https://code.tutsplus.com/series/create-a-drawing-app-on-android--cms-704
https://github.com/SueSmith/android-drawing-app
I started from the above codes.
I enhanced the above codes and used LightingColorFilter and BitmapShader. Here is my custom View class :

public class DrawingView extends View
{
    //drawing path    private Path drawPath;
    //drawing and canvas paint    private Paint drawPaint, canvasPaint;
    //initial color    private int paintColor = 0xFF660000;
    //canvas    private Canvas drawCanvas;
    //canvas bitmap    private Bitmap canvasBitmap, shaderBitmap;



    private float brushSize, lastBrushSize; 

    private boolean erase=false;

    public DrawingView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        setupDrawing();
        shaderBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.pattern);
    }


    private void setupDrawing()
    {
        brushSize = getResources().getInteger(R.integer.medium_size);
        lastBrushSize = brushSize;

        //get drawing area setup for interaction        drawPath = new Path(); 
        drawPaint = new Paint(); 

        drawPaint.setColor(paintColor);

        drawPaint.setAntiAlias(true);
        drawPaint.setStrokeWidth(brushSize);
        drawPaint.setStyle(Paint.Style.STROKE);
        drawPaint.setStrokeJoin(Paint.Join.ROUND);
        drawPaint.setStrokeCap(Paint.Cap.ROUND);

        canvasPaint = new Paint(Paint.DITHER_FLAG);
    }

    // Bitmap ve Canvas objects are created here    @Override    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        canvasBitmap = Bitmap.createBitmap(w,h,Bitmap.Config.ARGB_8888);
        drawCanvas =  new Canvas(canvasBitmap);
    }

    // invalidate() invokes onDraw()    @Override    protected void onDraw(Canvas canvas) {
        canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint);
        canvas.drawPath(drawPath, drawPaint);
    }

    @Override    public boolean onTouchEvent(MotionEvent event) {
        float touchX = event.getX();
        float touchY = event.getY();

        switch(event.getAction())
        {
            // When the user touches the View, we move to that position to start drawing.            case MotionEvent.ACTION_DOWN:
                drawPath.moveTo(touchX,touchY);
                break;
            // When they move their finger on the View, we draw the path along with their touch.            case MotionEvent.ACTION_MOVE:
                drawPath.lineTo(touchX, touchY);
                break;
            // When they lift their finger up off the View, we draw the Path and reset it for the next drawing operation.            case MotionEvent.ACTION_UP:
                drawCanvas.drawPath(drawPath, drawPaint);
                drawPath.reset();
                break;
            default:
                return false;
        }

        invalidate(); // Calling invalidate will cause the onDraw method to execute.        return true;
    }

    public void setColor(String newColor){
        paintColor = Color.parseColor(newColor);
        drawPaint.setColor(paintColor);
        ColorFilter filter = new LightingColorFilter(paintColor , 0x00000000 );
        drawPaint.setColorFilter(filter);
        invalidate();
    }

    public void setBrushSize(float newSize){
        //update size        float pixelAmount = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                newSize, getResources().getDisplayMetrics()); 
        brushSize = pixelAmount;
        drawPaint.setStrokeWidth(brushSize);
    }

    public void setLastBrushSize(float lastSize){
        lastBrushSize=lastSize;
    }
    public float getLastBrushSize(){
        return lastBrushSize;
    }

    public void setErase(boolean isErase)
    {
        //set erase true or false        erase=isErase;
        if(erase)
            drawPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
        else            drawPaint.setXfermode(null);
    }

    public void startNew(){
        drawCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
        invalidate();
    }

    public void setBitmapShader(){
        drawPaint.setShader(new BitmapShader(shaderBitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT));
        ColorFilter filter = new LightingColorFilter(paintColor , 0x00000000 );
        drawPaint.setColorFilter(filter);
    }
}


Android - HSV to RGB conversion(using Color.HSVToColor) and RGB to HSV conversion( using Color.RGBToHSV() or Color.colorToHSV() method )

/* hsv to rgb conversion  */
float [] colorsHSV = new float[]{1f,1f,1f};
int rgbColor = Color.HSVToColor(colorsHSV);
/* hsv to rgb conversion  */

/* Obtain red,green,color values, create a rgb using them */
int red = Color.red(rgbColor);
int green = Color.green(rgbColor);
int blue = Color.blue(rgbColor);
rgbColor = Color.rgb(red,green,blue);
/* Obtain red,green,color values, create a rgb using them */

/* rgb TO HSV conversion - way 1   */
float[] newHSV = new float[3];
Color.RGBToHSV(red,green,blue,newHSV);
/* rgb TO HSV conversion - way 1   */

/* rgb TO HSV conversion - way 2   */
float[] newHSV2 = new float[3];
Color.colorToHSV(rgbColor,newHSV2);
/* rgb TO HSV conversion - way 2   */

20 Şubat 2018 Salı

Android Dersleri 60 - XML kullanarak Android animasyonları uygulamak ve geliştirmek

Kaynaklar :
https://developer.android.com/guide/topics/resources/animation-resource.html
https://developer.android.com/reference/android/view/animation/Animation.html
https://developer.android.com/guide/topics/resources/animation-resource.html#Interpolators
http://www.androidhive.info/2013/06/android-working-with-xml-animations/

<alpha> kullanımı, fade-in ve fade-out animasyonları, AlphaAnimation class'ı

<alpha> :A fade-in or fade-out animation. Represents an AlphaAnimation.
attributes of <alpha> :android:fromAlpha    Float. Starting opacity offset, where 0.0 is transparent and 1.0 is opaque.android:toAlpha    Float. Ending opacity offset, where 0.0 is transparent and 1.0 is opaque.For more attributes supported by <alpha>, see the Animation class reference (of which, all XML attributes are inherrited by this element).AlphaAnimation class'Inın direct parent class'I Animation class'ıdır.

<set> : A container that holds other animation elements (<alpha>, <scale>, <translate>, <rotate>) or other <set> elements. Represents an AnimationSet.

Interpolator nedir?

An interpolator is an animation modifier defined in XML that affects the rate of change in an animation. This allows your existing animation effects to be accelerated, decelerated, repeated, bounced, etc.
An interpolator is applied to an animation element with the android:interpolator attribute, the value of which is a reference to an interpolator resource.
All interpolators available in Android are subclasses of the Interpolator class. For each interpolator class, Android includes a public resource you can reference in order to apply the interpolator to an animation using the android:interpolator attribute. The following table specifies the resource to use for each interpolator:
Interpolator classResource ID
AccelerateDecelerateInterpolator@android:anim/accelerate_decelerate_interpolator
AccelerateInterpolator@android:anim/accelerate_interpolator
AnticipateInterpolator@android:anim/anticipate_interpolator
AnticipateOvershootInterpolator@android:anim/anticipate_overshoot_interpolator
BounceInterpolator@android:anim/bounce_interpolator
CycleInterpolator@android:anim/cycle_interpolator
DecelerateInterpolator@android:anim/decelerate_interpolator
LinearInterpolator@android:anim/linear_interpolator
OvershootInterpolator@android:anim/overshoot_interpolator
Here's how you can apply one of these with the android:interpolator attribute:
<set android:interpolator="@android:anim/accelerate_interpolator">
    ...</set>

14 Şubat 2018 Çarşamba

Android Dersleri 99 - Soru Cevap

1 - SQLiteQueryBuilder.query() vs SQLiteDatabase.query()
What's the difference between these two approaches? For me it seems that the only benefit of SQLiteDatabase is its ability to work with different databases. Am I right?
Answer :
The primary method is SQLiteDatabase#rawQuery(). Both SQLiteDatabase#query() and SQLiteQueryBuilder are just helpers to compose the SQL.
The SQLiteDatabase#query() can only compose simple queries from one table. The SQLiteQueryBuilder can create joins, unions and such. Since SQLiteQueryBuilder is an extra object,
you'd only construct it if you need it's power.
Personally I think that any non-trivial SQL is easier to read as SQL than as pieces composed with helper like this, so I'd use rawQuery over SQLiteQueryBuilder,
but that's a matter of taste and how well you know SQL. The SQLiteQueryBuilder might also be useful if you have some common subqueries that you want to compose together in different ways.
In fact I would prefer (I use sqlite mainly using it's C API) to use prepared statements, because compilation of SQL is slow compared to it's execution, but I don't see that option in the Java interface.

2 - I found that onCreate of ContentProvider gets called first, even before the onCreate of my Activity. eg: Vogella Android SqlLite.
But I wanted to know how does it happen and why?
Is it because we register it as a provider in the Manifest?
Answer :
onCreate is to initialize your content provider on startup. This method is called for all registered content providers on the application main thread at application launch time.. yes ,it is because you register them in manifest...
while launching the app.. the manifest is checked for any contentproviders.. and if any..their oncreate is called.. so that they are available for your application as soon as it is created..
3 - Difference between GetWritableDatabase and getReadableDatabase
getWritableDatabase () method'u çağırdığımızda, tanımladığımız class'ın(SQLiteOpenHelper class'ından extend eden bir class tanımlamıştık) onCreate() method'u çağırılır otomatik olarak.
GetWritableDatabase() method is invoked to open the database in read-write mode, once the database disk space is full, the database will only be read but not write.
( Veritabanını read-write mode'da açmak için GetWritableDatabase() method'unu çağırırız. Eğer disk space full ise(veya başka bir hata olursa), artık disk'e daha fazla veri yazılamayacağı için veritabanı read write modda açılamaz, read modda açılır. )
-------------------
SQLiteDatabase getReadableDatabase ()
Create and/or open a database. This will be the same object returned by getWritableDatabase() unless some problem, such as a full disk, requires the database to be opened read-only. In that case, a read-only database object will be returned. If the problem is fixed, a future call to getWritableDatabase() may succeed, in which case the read-only database object will be closed and the read/write object will be returned in the future.
Like getWritableDatabase(), this method may take a long time to return, so you should not call it from the application main thread, including from ContentProvider.onCreate().
Returns
SQLiteDatabase a database object valid until getWritableDatabase() or close() is called.
Throws
SQLiteException if the database cannot be opened
( GetWritableDatabase() method'unu çağırdığımızda, veritabanı read-write mode'da açılmaya çalışılır. Eğer disk space full ise(veya başka bir hata olursa), artık disk'e daha fazla veri yazılamayacağı için veritabanı read write modda açılamaz, read modda açılır. )
-------------------
Difference between GetWritableDatabase and getReadableDatabase
They return the same object unless the disk is full or there is some permission error that forces to open the database in read-only mode. The name is a bit confusing though :)
( Disk full değilse ve başka herhangi bir hata oluşmazsa, her iki method'da read/write modda bir veritabanı yaratır veya böyle bir vertabanı zaten varsa bu veritabanını açar. )
As a rule of thumb you should call these methods outside the UI thread. Both can take a long time to return.
If you are not going to write the database just use getReadableDatabase as it will contribute to your code clarity and intention.
( Veritabanına yazmayacaksak, kodun daha temiz ve anlaşılır gözükmesi için getReadableDatabase() method'unu çağırmalıyız.  )
( Öenmli bir ayrıntı da şudur. getReadableDatabase() method'unda getWritableDatabase() method'u çağırılır. Yani getReadableDatabase() 'nu çağırırsak otomatik olarak getWritableDatabase() method'u da çağırılacaktır, db writable açılamazsa readable açılacaktır.  )
Her iki method da SQLiteDatabase object'e reference return eder.
ContentProvider class'ını extend eden BirthProvider isimli class'ın onCreate() method'unun implementation'ı aşağıdadır inceleyelim.
public boolean onCreate() {
// TODO Auto-generated method stub
Context context = getContext();
dbHelper = new DBHelper(context);
// permissions to be writable
database = dbHelper.getWritableDatabase();

   if(database == null)
    return false;
   else
    return true;
}

Android Dersleri 35.2 - Material Design, RecyclerView, CardView nedir?

15.9 - RecyclerView
Bu dersin tamamını içeren pdf'in link'i :
Kaynaklar :
It is a modernized version of the ListView and the GridView classes provided by the Android framework. It is supposed to be the successor of ListView and GridView, and it can be found in the latest support-v7 version. It enforced a programming style that results in good performance. It also comes with default animations for removing and adding elements.
RecyclerView has a more extensible framework, for example it provides the ability to implement both horizontal and vertical layouts.
Use the RecyclerView widget when you have data collections whose elements change at runtime based on user action or network events. (Runtime'da değişebilen bir listview istiyorsanız RecyclerView kullanmalısınız.)
RecyclerView allows to use different layout managers(LinearLayout, GridLayout) for positioning items.
Recycler view uses a ViewHolder to store references to the views for one entry in the recycler view. A ViewHolder class is a static inner class in your adapter which holds references to the relevant views. With these references, your code can avoid the time-consuming findViewById()method to update the widgets with new data. ( ViewHolder, Recycler view'deki bir entry için olan view'lere reference'ı tutar. ViewHolder class'ı, adapter'inizde bir static inner class'dır. ViewHolder class'ı, ilgili view'lere refer eden reference'ları tutar. Bu reference'lar sayesinde, çok pahalı olan findViewById()method'unu kullanmaya gerek kalmaz.  )

If you want to use a RecyclerView, you will need to work with the following: ( Eğer bir RecyclerView kullanmak istiyorsanız, aşağıdaki şeylere ihtiyacınız olacaktır. )
RecyclerView.Adapter - To handle the data collection and bind it to the view. (Örneğin bir array'deki verileri alıp view'lere gömme işini burada yaparız. )
Since RecyclerView.Adapter is abstract you will have to implement these three methods:
  • public VH onCreateViewHolder(ViewGroup parent, int viewType)
  • public void onBindViewHolder(VH holder, int position)
  • public int getItemCount()
LayoutManager - Helps in positioning the items. ( Item'ları dikey veya yatay listede mi veya grid olarak mı göstereceğiz bunu LayoutManager belirler. )
ItemAnimator - Helps with animating the items for common operations such as Addition or Removal of item. ( Runtime'da ListView'e yeni bir satır eklerken veya silerken animasyon göstermek için bu class kullanılır. )
Dataset(Data model) :  Örneğin bir array olabilir, bir satırda gösterilecek olan verileri tutar.
RecyclerView
Furthermore, it provides animation support for ListView items whenever they are added or removed, which had been extremely difficult to do in the current implementation. ( RecyclerView, runtime'da ListView'e yeni bir satır eklerken veya silerken animasyon göstermek için kullanılır. Bu işi RecyclerView olmadan sadece ListView class'ını kullanarak yapmak felaket zor bir iştir.  )
RecyclerView also begins to enforce the ViewHolder pattern too, which was already a recommended practice but now deeply integrated with this new framework. (RecyclerView, ViewHolder pattern'i zorunlu olarak kullandırır. ViewHolder pattern zaten kullanılması tavsiye edilen bir pattern'dır. Bu yeni framework ViewHolder pattern'ın kullanılmasını zorunlu kılmıştır. )
Compared to ListView
RecyclerView differs from its predecessor ListView primarily because of the following features: (RecyclerView'in, atası ListView'den farkları şunlardır: )
  • Required ViewHolder in Adapters - ListView adapters do not require the use of the ViewHolder pattern to improve performance. In contrast, implementing an adapter for RecyclerView requires the use of the ViewHolder pattern. (ListView adapter'lerinde performansı arttırmak için ViewHolder pattern kullanılabilir ancak bu zorunlu değildir. Buna karşın RecyclerView adapter'lerinde ViewHolder pattern kullanmak zorunludur.  )
  • Customizable Item Layouts - ListView can only layout items in a vertical linear arrangement and this cannot be customized. In contrast, the RecyclerView has a RecyclerView.LayoutManager that allows any item layouts including horizontal lists or staggered grids. ( ListView ile item'lar sadece vertical linear halinde yani dikey liste halinde gösterilebilirler, custom bir layout seçeneği yoktur, örneğin yatay liste halinde gösterilemezler. Buna karşın, RecyclerView RecyclerView.LayoutManager class'ına sahiptir, bu class item'ların yatayveya grid layout'larda gösterilebilmesini sağlar.  )
  • Easy Item Animations - ListView contains no special provisions through which one can animate the addition or deletion of items. In contrast, the RecyclerView has the RecyclerView.ItemAnimator class for handling item animations. ( ListView'de gösterilen bir satırın(item'ın) silinirken veya yenisi eklenirken bir animation gösterme seçeneği yoktur. Buna karşın, RecyclerView'in sahip olduğu RecyclerView.ItemAnimator class'ı item animation'ları sağlar. )
  • Manual Data Source - ListView had adapters for different sources such as ArrayAdapter and CursorAdapter for arrays and database results respectively. In contrast, the RecyclerView.Adapter requires a custom implementation to supply the data to the adapter. ( ListView array veya veritabanından okuyacağı veriler için ArrayAdapter ve CursorAdapter gibi adapter'leri kullanır. Buna karşın, RecyclerView 'de hazır bir adapter yoktur, RecyclerView.Adapter class'ı implement edilmelidir.  )
  • Manual Item Decoration - ListView has the android:divider property for easy dividers between items in the list. In contrast, RecyclerView requires the use of a RecyclerView.ItemDecoration object to setup much more manual divider decorations. ( ListView'de, listedeki item'lar arasında basit divider'lar göstermek için android:divider property kullanılır. Buna karşın, RecyclerView'in sahip olduğu RecyclerView.ItemDecoration class'ı kullanılarak çok daha manuel divider decoration'ları kullanılabilir. )
  • Manual Click Detection: ListView has an AdapterView.OnItemClickListener interface for binding to the click events for individual items in the list. In contrast, RecyclerView only has support for RecyclerView.OnItemTouchListener which manages individual touch events but has no built-in click handling. ( ListView'in sahip olduğu AdapterView.OnItemClickListener class'ı satırlara tıklama listener'ı register eder. Buna karşın RecyclerView'in sahip olduğu RecyclerView.OnItemTouchListener class'ı ne yapar anlamadım....  )
Components of a RecyclerView

a - LayoutManagers
RecyclerView needs to have a layout manager and an adapter to be instantiated. A layout manager positions item views inside a RecyclerView and determines when to reuse item views that are no longer visible to the user. ( RecyclerView'in bir layout manager'a ve bir adapter'e ihtiyacı vardır. Layout manager, RecyclerView'in içindeki item view'leri pozisyonlandırır ve kullanıcıya gösterilmeyen item view'lerin ne zaman tekrar kullanılacağını belirler. )

RecyclerView provides these built-in layout managers:
  • LinearLayoutManager shows items in a vertical or horizontal scrolling list.
  • GridLayoutManager shows items in a grid.
  • StaggeredGridLayoutManager shows items in a staggered grid.
To create a custom layout manager, extend the RecyclerView.LayoutManager class. Here is Dave Smith's talk on custom layout manager.
b - RecyclerView.Adapter
RecyclerView includes a new kind of adapter. It’s a similar approach to the ones you already used, but with some peculiarities, such as a required ViewHolder. You will have to override two main methods: one to inflate the view and its view holder, and another one to bind data to the view. The good thing about this is that first method is called only when we really need to create a new view. No need to check if it’s being recycled. ( RecyclerView'İn sahip olduğu adapter şimdiye kullandığımız adapter'lere benzer ancak bazı farklılıkları vardır mesela ViewHolder kullanmayı gerektirir. RecyclerView'in adapter'inde şu 2 method'u override etmeliyiz:
- onCreateViewHolder() : view'i ve view holder'ı inflate eder. Bu method, sadece yeni bir view yaratılacağı zaman çağırılır. View'in recycle edilip edilmediğini check etmeye gerek yoktur. Adapter class'ında tanımladığımız inner ViewHolder class'ından bir object yaratılır, onCreateViewHolder() method'u bu object'i return eder. Adapter mContacts listesindeki verileri view'lere bind edecektir, getItemCount() method'u da override edilmeli mContacts listesinin size'Inı return etmelidir.
- onBindViewHolder() : verileri view'e bind eder. )
public class ContactsAdapter extends
   RecyclerView.Adapter<ContactsAdapter.ViewHolder> {

   private List<Contact> mContacts;

   // ... constructor and member variables
   public static class ViewHolder extends RecyclerView.ViewHolder
   {
...
   }

   // Usually involves inflating a layout from XML and returning the holder
   @Override
   public ContactsAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
       Context context = parent.getContext();
       LayoutInflater inflater = LayoutInflater.from(context);

       // Inflate the custom layout
       View contactView = inflater.inflate(R.layout.item_contact, parent, false);

       // Return a new holder instance
       ViewHolder viewHolder = new ViewHolder(contactView);
       return viewHolder;
   }

   // Involves populating data into the item through holder
   @Override
   public void onBindViewHolder(ContactsAdapter.ViewHolder viewHolder, int position) {
       // Get the data model based on position
       Contact contact = mContacts.get(position);

       // Set item views based on your views and data model
       TextView textView = viewHolder.nameTextView;
       textView.setText(contact.getName());
       Button button = viewHolder.messageButton;
       button.setText("Message");
   }

   // Returns the total count of items in the list
   @Override
   public int getItemCount() {
       return mContacts.size();
   }


}


c - ItemAnimator
RecyclerView.ItemAnimator will animate ViewGroup modifications such as add/delete/select that are notified to adapter. DefaultItemAnimator can be used for basic default animations and works quite well. See the section of this guide for more information. ( ViewGroup'da ekleme,silme,seçme yapıldığında RecyclerView.ItemAnimator class'ı animasyon göstermeyi sağlayacaktır. )
Using the RecyclerView
Using a RecyclerView has the following key steps:
  1. Gradle dosyasına şu RecyclerView support library'yi ekle :
dependencies {
   ...
   compile 'com.android.support:recyclerview-v7:25.2.0'
}
  1. Define a model class to use as the data source. ( Örneğin, Contact isimli liste RecyclerView'de gösterilecek satırlardaki view'lere bind edilecek diyelim. Bu durumda Contact class'ı bizim model class'ımızdır, data source olarak kullanılacaktır. )
  2. Add a RecyclerView to your activity to display the items. ( Activity'nin layout xml'ine RecyclerView element eklemeliyiz. )
  3. Create a custom row layout XML file to visualize the item. ( RecyclerView'de gösterilecek herbir satırın layout'unu bir xml dosyasında tanımlarız. )
  4. Create a RecyclerView.Adapter and ViewHolder to render the item. (RecyclerView.Adapter class'ını extend eden bir class tanımlanır. Bu class'da RecyclerView.ViewHolder class'ını extend eden bir inner class tanımlanır.  )
  5. Bind the adapter to the data source to populate the RecyclerView. (RecyclerView.Adapter class'ında gerekli method'lar override edilerek verilerin view'ler bind edilmesi sağlanır.  )
The steps are explained in more detail below. ( Şimdi bu adımları detaylıca inceleyelim. )
1 - Installation
Make sure the RecyclerView support library is listed as a dependency in your app/build.gradle:
dependencies {
   ...
   compile 'com.android.support:recyclerview-v7:25.2.0'
}
2 - Defining a Model
Every RecyclerView is backed by a source for data. In this case, we will define a Contact class which represents the data model being displayed by the RecyclerView: (RecyclerView'de gösterilecek satırlardaki view'lere, bu class'ın object'leri bind edilecektir. )
public class Contact {
   private String mName;
   private boolean mOnline;

   public Contact(String name, boolean online) {
       mName = name;
       mOnline = online;
   }

   public String getName() {
       return mName;
   }

   public boolean isOnline() {
       return mOnline;
   }

   private static int lastContactId = 0;

   public static ArrayList<Contact> createContactsList(int numContacts)
  {
       ArrayList<Contact> contacts = new ArrayList<Contact>();
       for (int i = 1; i <= numContacts; i++)
      {
           contacts.add(new Contact("Person " + ++lastContactId, i <= numContacts / 2));
       }
       return contacts;
   }
}
3- Add the RecyclerView element within layout xml
Inside the desired activity layout XML file in res/layout/activity_users.xml, let's add the RecyclerView from the support library: ( Activity'nin layout xml dosyasına, support library'deki RecyclerView element eklenir.  )
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="match_parent"
   android:layout_height="match_parent" >

   <android.support.v7.widget.RecyclerView
     android:id="@+id/rvContacts"
     android:layout_width="match_parent"
     android:layout_height="match_parent" />

</RelativeLayout>
4 - Creating the Custom Row Layout
Before we create the adapter, let's define the XML layout file that will be used for each row within the list. This item layout for now should contain a horizontal linear layout with a textview for the name and a button to message the person: ( Adapter'ü tanımlamadan önce, RecyclerView'de gösterilecek herbir satırın layout'unu bir xml dosyasında tanımlarız. Yatay linear layout içerisinde ismi gösteren bir textview ve sağda bir buton gösterilir. )
This layout file can be created in res/layout/item_contact.xml and will be rendered for each item row. Note that you should be using wrap_content for the layout_height because RecyclerView versions prior to 23.2.1 previously ignored layout parameters. See this link for more context. ( Herbir satır'da  bu layout gösterilecektir. Root layout olan LinearLayout'un layout_height'ı wrap_content olmalıdır. )
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
       xmlns:android="http://schemas.android.com/apk/res/android"
       android:orientation="horizontal"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:paddingTop="10dp"
       android:paddingBottom="10dp" >

   <TextView
       android:id="@+id/contact_name"
       android:layout_width="0dp"
       android:layout_height="wrap_content"
       android:layout_weight="1"
       />

   <Button
       android:id="@+id/message_button"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:paddingLeft="16dp"
       android:paddingRight="16dp"
       android:textSize="10sp"
       />
</LinearLayout>
With the custom item layout complete, let's create the adapter to populate the data into the recycler view. ( RecyclerView'deki satırların layout'larını tanımladık. Şimdi ise satırlardaki view'lere verileri yükleyeceğiz.)
Creating the RecyclerView.Adapter
Here we need to create the adapter which will actually populate the data into the RecyclerView. The adapter's role is to convert an object at a position into a list row item to be inserted. ( Şimdi ise bir adapter tanımlayacağız. Adapter'Ün görevi, verileri RecyclerView'e doldurmaktır. Diğer bir deyişle object'leri satırlardaki view'lere doldurmaktır. )
However with a RecyclerView the adapter requires the existence of a "ViewHolder" object which describes and provides access to all the views within each item row. We can create the basic empty adapter and holder together in ContactsAdapter.java as follows: (RecyclerView'de, ViewHolder inner class tanımlanır. ViewHolder class'ında, herbir satırdaki view'lere erişilir. Aşağıda boş bir adapter class'ı tanımladık ve inner ViewHolder class'ı tanımladık. )
// Create the basic adapter extending from RecyclerView.Adapter (RecyclerView.Adapter<inner ViewHolder class> class'ını extend eden bir class tanımladık.)
// Note that we specify the custom ViewHolder which gives us access to our views ( Bu class'da RecyclerView.ViewHolder class'ını extend eden bir class tanımlayacağız. Bu ViewHolder class'ında satırlardaki view'lere erişeceğiz. )
public class ContactsAdapter extends
   RecyclerView.Adapter<ContactsAdapter.ViewHolder> {

   // Provide a direct reference to each of the views within a data item
   // Used to cache the views within the item layout for fast access. (ViewHolder'da gösterilecek herbir satırdaki tüm view'lere ViewHolder class'ında erişelim. Bu view'ler cache'lenecektir.)
   public static class ViewHolder extends RecyclerView.ViewHolder {
       Herbir satırın layout'unda TextView ve Button view göstermek istiyoruz diyelim. Bu durumda bu 2 view'e refer eden reference variable declare ederiz ViewHolder class'ında. ViewHolder class'ının constructor'ında ise bu view object'lere erişiriz.
       public TextView nameTextView;
       public Button messageButton;

       public ViewHolder(View itemView) {
           super(itemView);
           nameTextView = (TextView) itemView.findViewById(R.id.contact_name);
           messageButton = (Button) itemView.findViewById(R.id.message_button);
       }
   }
}
Now that we've defined the basic adapter and ViewHolder, we need to begin filling in our adapter. First, let's store a member variable for the list of contacts and pass the list in through our constructor: ( Yukarıda basit bir adapter ve ViewHolder tanımladık. Ama tabi işimiz daha bitmedi adapter class'ını geliştirmeye devam edeceğiz. Adapter class'ında contact listesine refer eden bir reference variable declare ederiz:
private List<Contact> mContacts;
Context object'e refer eden bir reference variable declare ederiz:
private Context mContext;
Adapter class'ımız için yukarıdaki 2 reference variable'a assign edeceğimiz 2 parametre alan bir constructor tanımlarız.
public ContactsAdapter(Context context, List<Contact> contacts)
{
       mContacts = contacts;
       mContext = context;
}
Sonra ise context object'i return eden bir method tanımlarız:
private Context getContext()
{
      return mContext;
} )
public class ContactsAdapter extends
   RecyclerView.Adapter<ContactsAdapter.ViewHolder> {

   // ... view holder defined above...

   // Store a member variable for the contacts
   private List<Contact> mContacts;
   // Store the context for easy access
   private Context mContext;

   // Pass in the contact array into the constructor
   public ContactsAdapter(Context context, List<Contact> contacts) {
       mContacts = contacts;
       mContext = context;
   }

   // Easy access to the context object in the recyclerview
   private Context getContext() {
      return mContext;
   }
}
Every adapter has three primary methods: onCreateViewHolder to inflate the item layout and create the holder, onBindViewHolder to set the view attributes based on the data and getItemCount to determine the number of items. We need to implement all three to finish the adapter: ( Adapter'ü tanımlama işimiz hala bitmedi. Yukarıdaki yaptıklarımıza ek olarak, adapter class'ımızda şu method'ları tanımlamalıyız, aşağıdaki gibi.
- onCreateViewHolder() : saturların layout'unu burada belirtiriz ve ViewHolder class'ından bir object yaratıp return ederiz.
- onBindViewHolder() : Verileri view'lere set ederiz. Bu method herbir satır için otomatik olarak çağırılır, method'un aldığı 2. parametreden hangi satır için çağırıldığı bilinir. Dolayısıyla örneğin 3.satır için çağırılırsa mContact List object'in 3. poziyonundaki Contact object elde edilir. Sonra ViewHolder object'in içerdiği textView elde edilir. Bu textView'e, az önce elde edilen Contact object'in içerdiği name variable'ının değeri set edilir. Benzer şekilde ViewHolder object'in içerdiği Button object elde edilip bu butona text olarak ise "Message" set edilir.
public void onBindViewHolder(ContactsAdapter.ViewHolder viewHolder, int position) {
       Contact contact = mContacts.get(position);
       TextView textView = viewHolder.nameTextView;
       textView.setText(contact.getName());
       Button button = viewHolder.messageButton;
       button.setText("Message");
   }
- getItemCount() : RecyclerView'de gösterilecek satır sayısını return eder. )
public class ContactsAdapter extends
   RecyclerView.Adapter<ContactsAdapter.ViewHolder> {

   // ... constructor and member variables

   // Usually involves inflating a layout from XML and returning the holder
   @Override
   public ContactsAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
       Context context = parent.getContext();
       LayoutInflater inflater = LayoutInflater.from(context);

       // Inflate the custom layout
       View contactView = inflater.inflate(R.layout.item_contact, parent, false);

       // Return a new holder instance ( Tanımladığımız inner ViewHolder class'ının constructor'ına satır layout'Unu belirten View object verilerek elde edilen object return edilir. )
       ViewHolder viewHolder = new ViewHolder(contactView);
       return viewHolder;
   }

   // Involves populating data into the item through holder
   @Override
   public void onBindViewHolder(ContactsAdapter.ViewHolder viewHolder, int position) {
       // Get the data model based on position
       Contact contact = mContacts.get(position);

       // Set item views based on your views and data model
       TextView textView = viewHolder.nameTextView;
       textView.setText(contact.getName());
       Button button = viewHolder.messageButton;
       button.setText("Message");
   }

   // Returns the total count of items in the list
   @Override
   public int getItemCount() {
       return mContacts.size();
   }
}
With the adapter completed, all that is remaining is to bind the data from the adapter into the RecyclerView. ( Adapter class'ımızı tanımlamayı bitirdik. Şimdi geriye sadece, adapter'deki verileri RecyclerView'e bind etmek kaldı. )
Binding the Adapter to the RecyclerView
In our activity, we will populate a set of sample users which should be displayed in the RecyclerView. ( RecyclerView'i hangi activity'de göstermek istiyorsak, o activity class'ının onCreate() method'una aşağıdaki kodları yazarız.Bu activity'nin layout xml'ine RecyclerView element koymuştuk, bu element'i kullanarak bir RecyclerView object elde ederiz:
RecyclerView rvContacts = (RecyclerView) findViewById(R.id.rvContacts);
20 tane Contact object içeren bir List object elde ederiz:
contacts = Contact.createContactsList(20);
Tanımladığımız adapter class'ından bir object yaratırız. Constructor'a 1. argument olarak Context object, 2.argument olarak ise data source olarak kullanılacak List object'i veririz :
ContactsAdapter adapter = new ContactsAdapter(this, contacts);
RecyclerView object'in setAdapter(adapter) method'unu çağırarak RecyclerView object ile adapter object'i birbirine bağlarız(bind ederiz).
RecyclerView'in layout'unu belirlemek için RecyclerView object'in setLayoutManager() method'unu çağırırız. Bu örnekte RecyclerView'in layout'u linear layout yapılmıştır :
        rvContacts.setLayoutManager(new LinearLayoutManager(this));
)
public class UserListActivity extends AppCompatActivity {

    ArrayList<Contact> contacts;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // ...
        // Lookup the recyclerview in activity layout
        RecyclerView rvContacts = (RecyclerView) findViewById(R.id.rvContacts);

        // Initialize contacts
        contacts = Contact.createContactsList(20);
        // Create adapter passing in the sample user data
        ContactsAdapter adapter = new ContactsAdapter(this, contacts);
        // Attach the adapter to the recyclerview to populate items
        rvContacts.setAdapter(adapter);
        // Set layout manager to position the items
        rvContacts.setLayoutManager(new LinearLayoutManager(this));
        // That's all!
    }
}
Finally, compile and run the app and you should see something like the screenshot below. If you create enough items and scroll through the list, the views will be recycled and far smoother by default than the ListView widget: ( Şimdi projemizi çalıştırdığımızda aşağıdaki gibi bir ekran görürüz. 20 item'lık(satırlık) bu RecyclerView'de scroll ettiğimizde ListView'den çok daha düzgün bir sonuç alırız. ListView'e göre çok daha hızlı bir şekilde scroll edebiliriz, view'ler çok hızlı bir şekilde recycle edilebilir. )
Şimdiye kadar öğrendiklerimizi uyguladığımızda yukarıdaki gibi bir output elde ettik. Bu projeye şuradan erişebilirsiniz :
16_9_RecyclerView

Notifying the Adapter
Unlike ListView, there is no way to add or remove items directly through the RecyclerView adapter. You need to make changes to the data source directly and notify the adapter of any changes. ( ListView'de doğrudan adapter'ü kullanarak listview'e yeni bir satır ekleyebiliriz,silebiliriz. Buna karşın, doğrudan RecyclerView adapter'ü kullanarak yeni bir satır eklemek veya varolan bir satırı silmek mümkün değildir.
RecyclerView'e satır eklemek için, doğrudan data source'da değişiklik yapmalıyız ve adapter'ü bu değişiklikten haberdar etmeliyiz(notify). )
Also, whenever adding or removing elements, always make changes to the existing list. For instance, reinitializing the list of Contacts such as the following will not affect the adapter, since it has a memory reference to the old list: ( Dikkat etmemiz gereken önemli bir nokta ise şudur, satır eklemek silmek için varolan list object üzerinde değişiklik yapmalıyız, yeni bir list object kullanmamalıyız yani. Örneğin aşağıdaki gibi yeni bir Contact list object yaratmak adapter'ü etkilemez, çünkü adapter eski list object'e refer eder. )

// do not reinitialize an existing reference used by an adapter
contacts = Contact.createContactsList(5);
Instead, you need to act directly on the existing reference: ( Yukarıdaki kod çalışmaz. Bunun yerine aşağıdaki gibi, varolan list object'e yeni elemanlar eklemeliyiz: )
// add to the existing list
contacts.addAll(Contact.createContactsList(5));
There are many methods available to use when notifying the adapter of different changes: ( Sonrasında ise adapter'ü data source'daki yani list object'deki değişiklikten haberdar etmeliyiz(notify). Adapter'ü notify etmek için kullanılabilecek method'lar aşağıda gösterilmiştir : )
Method
Description
notifyItemChanged(int pos)
Notify that item at position has changed. ( Listenin belirli bir pozisyonundaki elemanı değiştirirsek sonrasında bu method'u çağırmalıyız.  )
notifyItemInserted(int pos)
Notify that item reflected at position has been newly inserted. (Listenin belirli bir pozisyonuna eleman eklersek sonrasında bu method'u çağırmalıyız. )
notifyItemRemoved(int pos)
Notify that items previously located at position has been removed from the data set. (Listenin belirli bir pozisyonundaki elemanı silersek sonrasında bu method'u çağırmalıyız. )
notifyDataSetChanged()
Notify that the dataset has changed.
Use only as last resort. ( Listede herhangi bir değişiklik yaptıktan sonra bu method'u çağırarak da adapter'ü haberdar edebiliriz. Başka hiçbir seçeneğimiz yoksa bu method'u çağırmalıyız. )
We can use these from the activity or fragment: ( Yukarıdakileri method'ları activity veya fragment'ın içerisinde çağırabiliriz. Aşağıdaki örneği inceleyelim. contacts listesinin 0.pozisyonuna yeni bir object ekleriz, sonra ise adapter object'in notifyItemInserted(0) method'unu çağırarak, adapter'e 0.pozisyona bir eleman eklediğimizi söyleriz. )
// Add a new contact
contacts.add(0, new Contact("Barney", true));
// Notify the adapter that an item was inserted at position 0
adapter.notifyItemInserted(0);
Every time we want to add or remove items from the RecyclerView, we will need to explicitly inform to the adapter of the event. Unlike the ListView adapter, a RecyclerView adapter should not rely on notifyDataSetChanged() since the more granular actions should be used. See the API documentation for more details. ( RecyclerView'e item(satır) eklemek/silmek istediğimiz her zaman mutlaka explicit bir şekilde adapter'ü bundan haberdar etmeliyiz. ListView adapter'ü notifyDataSetChanged() method'una dayanır, RecyclerView adapter'ü ise notifyDataSetChanged() method'una dayanmaz.  )
Also, if you are intending to update an existing list, make sure to get the current count of items before making any changes. For instance, a getItemCount() on the adapter should be called to record the first index that will be changed. ( Varolan bir listeyi güncellemek istiyorsanız, önce listenin size'ını bulup bi kenara yazın. Örneğin, listedeki değştirilecek olan index'i belirtmek için getItemCount()'un return ettiği değer kullanılabilir. )
Aşağıdaki örneği inceleyelim. adapter object'in getItemCount() method'U çağırılarak data source'un yani listenin size'ı elde edilir:
int curSize = adapter.getItemCount();
20 tane Contact object içeren bir ArrayList object yaratırız:
ArrayList<Contact> newItems = Contact.createContactsList(20);
Varolan listenin sonuna yukarıda yarattığımız 20 elemanlı ArrayList object'i ekleriz:
contacts.addAll(newItems);
Adapter'e şunu haber veririz, varolan listenin 20.index'inden itibaren 20 eleman ekleriz. 20 eleman'In index'leri 0'dan 19'a kadardır. Yani listenin sonuna eklenecek ilk elemanın index'i 20 olacaktır bu yüzden notifyItemRangeInserted() method'una 1.argument olarak 20 yani ilk listenin size'ını argument olarak veririz. 2.argument olarak ise listeye eklenecek eleman sayısını veririz:
adapter.notifyItemRangeInserted(curSize, newItems.size());

// record this value before making any changes to the existing list
int curSize = adapter.getItemCount();

// replace this line with wherever you get new records
ArrayList<Contact> newItems = Contact.createContactsList(20);

// update the existing list
contacts.addAll(newItems);
// curSize should represent the first element that got added
// newItems.size() represents the itemCount
adapter.notifyItemRangeInserted(curSize, newItems.size());
Diffing Larger Changes
Often times there are cases when changes to your list are more complex (i.e. sorting an existing list) and it cannot be easily determined whether each row changed. In this cases, you would normally have to call notifyDataSetChanged() on the entire adapter to update the entire screen, which eliminates the ability to perform animation sequences to showcase what changed. ( Eğer listede çok fazla değişiklik yaparsak, örneğin varolan bir listeyi belirli bir kritere göre sort edersek, notifyDataSetChanged() method'unu çağırarak ekranın tamamının güncellenmesi sağlanır, ancak bu method'u çağırınca değişen satırlarda animasyon gerçekleşmez. Bu case'i handle etmek için support library'deki DiffUtil class'ı kullanılabilir. )
A new DiffUtil class has been added in the v24.2.0 of the support library to help compute the difference between the old and new list. This class uses the same algorithm used for computing line changes in source code (the diff utility program), so it usually fairly fast. It is recommended however for larger lists that you execute this computation in a background thread. ( DiffUtil class'ı eski ve yeni liste arasındaki farkları hesaplar. Herhangi bir source code'da değişiklik yaptığımızda satırlardaki değişiklikleri bulmak için diff utility programını kullanırdık Linux komut satırında diff komutunu vererek hatırla, işte DiffUtil class'ı da bahsettiğimiz bu diff utility programını kullandığı için çok hızlı çalışır. Büyük listeler için bu class'ı kullanacaksak, ilgili hesaplamayı arka planda çalışan bir thread'de yapmalıyız. )
To use the DiffUtil class, you need to first implement a class that implements the DiffUtil.Callback that accepts the old and new list: (DiffUtil class'ını kullanabilmek için önce, DiffUtil.Callback class'ını extend eden bir class tanımlamalıyız, bu class'ın constructor'ı parametre olarak eski listeyi ve yeni listeyi alır. Eski ve yeni listenin size'ını return eden 2 method tanımlarız. Eski ve yeni list object'ler aynı mı diye check etmek için areItemsTheSame() method'u override edilir. Eski ve yeni list object'lerin içerikleri aynı mı diye check etmek için areContentsTheSame() method'u override edilir. )
public class ContactDiffCallback extends DiffUtil.Callback {

   private List<Contact> mOldList; // Eski liste
   private List<Contact> mNewList; // Yeni liste

   public ContactDiffCallback(List<Contact> oldList, List<Contact> newList) {
       this.mOldList = oldList; // Eski listeyi kaydederiz.
       this.mNewList = newList; // Yeni listeyi kaydederiz.
   }
   @Override
   public int getOldListSize() {
       return mOldList.size();
   }

   @Override
   public int getNewListSize() {
       return mNewList.size();
   }

   @Override
   public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
       // add a unique ID property on Contact and expose a getId() method
       return mOldList.get(oldItemPosition).getId() == mNewList.get(newItemPosition).getId();
   }

   @Override
   public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
       Contact oldContact = mOldList.get(oldItemPosition);
       Contact newContact = mNewList.get(newItemPosition);

       if (oldContact.getName() == newContact.getName() && oldContact.isOnline() == newContact.isOnline()) {
           return true;
       }
       return false;
   }
}
Next, you would implement a swapItems() method on your adapter to perform the diff and then invoke dispatchUpdates() to notify the adapter whether the element was inserted, removed, moved, or changed: ( Sonra ise adapter class'ımızda swapItems() isimli bir method tanımlarız. swapItems() method'unda, yukarıda tanımladığımız ContactDiffCallback class'ının constructor'ına parametre olarak eski ve yeni liste verilerek bir object yaratırız:
final ContactDiffCallback diffCallback = new ContactDiffCallback(this.mContacts, contacts);
Sonra DiffUtil.calculateDiff() method'unu çağırarak bir DiffUtil.DiffResult object elde ederiz:
final DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(diffCallback);
Sonra eski listenin tüm elemanlarını sileriz ve eski listeye yenin listenin içeriğini koyarız:
this.mContacts.clear();
this.mContacts.addAll(contacts);
Sonra DiffUtil.DiffResult object'in dispatchUpdatesTo(this) method'u çağırılarak adapter listedeki değişiklikten haberdar edilmiştir :
diffResult.dispatchUpdatesTo(this); )
public class ContactsAdapter extends
       RecyclerView.Adapter<ContactsAdapter.ViewHolder> {

 public void swapItems(List<Contact> contacts) {
       // compute diffs
       final ContactDiffCallback diffCallback = new ContactDiffCallback(this.mContacts, contacts);
       final DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(diffCallback);

       // clear contacts and add
       this.mContacts.clear();
       this.mContacts.addAll(contacts);

       diffResult.dispatchUpdatesTo(this); // calls adapter's notify methods after diff is computed
   }
}

16_9_2_RecyclerView_SortingList
For a working example, see this sample code. Linkteki source code'u kullanarak 16_9_2_RecyclerView_SortingList isimli projeyi geliştirdim.

Output :
 
Sort by name :
Sort by rating :
Sort by Year of Birth :
Şimdi source kodları kısaca inceleyelim.

Actor.java : Model class'ımızdır.
ActorAdapter.java : Adapter class'ının sahip olduğu data source yani ArrayList, Actor class'ı type'ında element'lere sahiptir. Bu class'da daha önce açıkladığımız swapItems() method'u tanımlanmıştır. SwapItems() method'unda ActorDiffCallback class'ından bir object yaratılır, ActorDiffCallback class'ı bir sonraki sayfada incelenmiştir.
Ayrıca toolbar'a bu 3 tane buton koyacağız, swapItems() method'u bu butonlara tıklayınca çağırılacaktır:

ActorRepository.java
ActorDiffCallback :
MainActivity.java

activity_main.xml
item_actor.xml

Scrolling to New Items
If we are inserting elements to the front of the list and wish to maintain the position at the top, we can set the scroll position to the 1st element:  ( Listenin başına eleman eklemek ve ekranda scrolling alanında bu elemanın da görünür olmasını istiyorsak, önce adapter'e 0. index'e eleman eklediğimizi haber veririz sonra scroll position'ı 0.eleman olarak set ederiz aşağıdaki gibi. )
adapter.notifyItemInserted(0);
rvContacts.scrollToPosition(0);   // index 0 position
If we are adding items to the end and wish to scroll to the bottom as items are added, we can notify the adapter that an additional element has been added and can call smoothScrollToPosition() on the RecyclerView: (Listenin sonuna eleman eklemek ve ekranda scrolling alanında bu elemanın da görünür olmasını istiyorsak, önce adapter'e son index'e eleman eklediğimizi haber veririz sonra scroll position'ı son eleman olarak set ederiz aşağıdaki gibi. Aşağıdaki kodda scrollToPosition() method'unu kullandık, smoothScrollToPosition()  method'unun ne işe yaradığını ise bilmiyorum.  )

adapter.notifyItemInserted(contacts.size() - 1);  // contacts.size() - 1 is the last element position
rvContacts.scrollToPosition(mAdapter.getItemCount() - 1);  // update based on adapter

Implementing Endless Scrolling
To implement fetching more data and appending to the end of the list as the user scrolls towards the bottom, use the addOnScrollListener() from the RecyclerView and add an onLoadMore method leveraging the EndlessScrollViewScrollListener document in the guide. ( Tumblr'daki bir sayfayı hatırla, en aşağı scroll ettiğimizde yeni şey yükleniyor alta ve daha aşağı scroll edebiliyoruz. Bu böyle taa content bitene kadar devam eder biz scroll ettikçe o daha fazla content yükler. Buradaki olay endless scrolling'dir yani. Bunun için RecyclerView object'in addOnScrollListener() method'unu çağırmalıyız. Burada daha fazla ayrıntıya girmeyeceğim. Ayrıntı için şu adrese bakabilirsin : https://guidess.codepath.com/android/using-the-recyclerview#configuring-the-recyclerview   )

Configuring the RecyclerView
The RecyclerView is quite flexible and customizable. Several of the options available are shown below.
Performance
setHasFixedSize() is used to let the RecyclerView that its size will keep the same. This information will be used to optimize itself.
recyclerView.setHasFixedSize(true);
RecyclerView can perform several optimizations if it can know in advance that RecyclerView's size is not affected by the adapter contents. RecyclerView can still change its size based on other factors (e.g. its parent's size) but this size calculation cannot depend on the size of its children or contents of its adapter (except the number of items in the adapter).
If your use of RecyclerView falls into this category, set this to true.
Layouts
The positioning of the items is configured using the layout manager. By default, we can choose between
- LinearLayoutManager,
- GridLayoutManager, and
- StaggeredGridLayoutManager.
Linear displays items either vertically or horizontally:

// Also supports `LinearLayoutManager.HORIZONTAL`
LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
// Optionally customize the position you want to default scroll to
layoutManager.scrollToPosition(0);
// Attach layout manager to the RecyclerView
recyclerView.setLayoutManager(layoutManager);

Displaying items in a grid or staggered grid works similarly:

// 1. parametre column sayısıdır, 1. parametre ise orientation'ıdır.
StaggeredGridLayoutManager gridLayoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
// Attach the layout manager to the recycler view. ( RecyclerView'e layout manager'ı bağlarız: )
recyclerView.setLayoutManager(gridLayoutManager);

Grid ve staggered grid arasındaki fark nedir? Okuyalım :
Heterogenous Layouts inside RecyclerView
See this guide if you want to inflate multiple types of rows inside a single RecyclerView. This is useful for feeds which contain various different types of items within a single list.
Örneğin Facebook'un veya Tumblr'ın news feed'ini düşün. News Feed'de bir fotoğraf, video, statüs güncelleme, link paylaşma gibi paylaşımlar görebiliriz. News Feed'de bir ListView veya RecyclerView vardır ancak herbir satır aynı değildir, kimi satırda video gösterilir, kimi satırda fotoğraf kimi satırda link paylaşımı vs. gösterilir. Şimdiye kadarki RecyclerView ve ListView geliştirmelerimizde tüm satırların layout'ları aynıydı. Şimdi ise farklı satır layout'ları nasıl geliştirebiliriz, örneğin video gösterilecekse farklı bir satır layout gösterilsin,  fotoğraf gösterilecekse farklı bir satır layout gösterilsin vs. istiyoruz.
Aşağıdaki linkten ListView'de Heterogenous Layout kullanmak anlatılır ancak ListView verimsiz olduğu için bu konuyu atlayalım.
RecyclerView verimlidir şimdi RecyclerView'de Heterogenous Layout göstermeyi aşağıdaki linkten öğreneceğiz:

16_9_1_RecyclerView isimli projeyi geliştirip
16_9_1_RecyclerView2_heterogenous_layout
isimli projeyi geliştireceğiz bu derste.....