/**
* https://gist.github.com/chrisbanes/8391b5adb9ee42180893300850ed02f2
*
* 코디네이너레이아웃 앱바레이아웃.behavior
*
* 사용법.
* code
* AppBarLayout abl = findViewById(R.id.app_bar);
* ((CoordinatorLayout.LayoutParams) abl.getLayoutParams()).setBehavior(new FixAppBarLayoutBehavior());
*
* xml에서 사용됨.
* xml
* <android.support.design.widget.AppBarLayout
* android:id="@+id/app_bar"
* android:layout_height="..."
* android:layout_width="..."
* app:layout_behavior="your.package.FixAppBarLayoutBehavior">
*/
class FixAppBarLayoutBehavior(context: Context?, attrs: AttributeSet?) :
AppBarLayout.Behavior(context, attrs) {

override fun onNestedScroll(coordinatorLayout: CoordinatorLayout, child: AppBarLayout,
target: View, dxConsumed: Int, dyConsumed: Int, dxUnconsumed: Int,
dyUnconsumed: Int, type: Int) {
super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed,
dyUnconsumed, type)
stopNestedScrollIfNeeded(dyUnconsumed, child, target, type)
}

override fun onNestedPreScroll(coordinatorLayout: CoordinatorLayout, child: AppBarLayout,
target: View, dx: Int, dy: Int, consumed: IntArray, type: Int) {
super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed, type)
stopNestedScrollIfNeeded(dy, child, target, type)
}

private fun stopNestedScrollIfNeeded(dy: Int, child: AppBarLayout, target: View, type: Int) {
if (type == ViewCompat.TYPE_NON_TOUCH) {
val currOffset = topAndBottomOffset
if (dy < 0 && currOffset == 0 || dy > 0 && currOffset == -child.totalScrollRange) {
ViewCompat.stopNestedScroll(target, ViewCompat.TYPE_NON_TOUCH)
}
}
}
}


프로그램에서 함수는 스택구조이다.
0->1->2->3->3->2->1->0

MVP 패턴 
모델, 뷰, 프레젠터


Model : 데이터 처리
View : xml을 가지는 액티비티 또는 프래그먼트가 됨.
Presenter : 뷰와 모델을 연결해주는 인터페이스


view    <->  Presenter <-> Model 
뷰와 프레젠터는 화면을 그리기 위한 처리만한다.

프레젠터와 모델은 데이터 처리만 한다.(추가, 갱신, 삭제)

프레젠터가 모델에 데이터를 처리 요청을 하고 값을 돌려 받으면
프레젠터는 뷰에게 값만 전달하여 화면 변경을 한다.

액션(서버통신) 또는 데이터 가져오는 클래스가 모델이 된다.


소스예제.


1. 데이터 클래스 생성.
/**데이터를 생성하는 클래스.*/
class MakeData {

/**어레이리스트 형식으로 객체생성*/
    fun makeList(): MutableList {

        var data = mutableListOf()
        for (i in 0 until 50) {
            data.add("$i element row")
        }
        return data
    }

}

mvp 패턴에서 사용할 Base interface 등록

2. 인터페이스 생성.
/**뷰에서 구현할 인터페이스.*/
interface BaseView {
    /**제네릭으로 상속받을 프레젠터 클래스.*/
    val presenter: T
}

3. 인터페이스 생성.
/**프레젠터에서 구현할 인터페이스*/
interface BasePresent {
    /**
     * 제네릭으로 상속받을 뷰 클래스.
     * 최초 객체 생성이 null로 생성되므로 null type 선언.
     */
    val view: T?
}

4. 계약자 인터페이스 생성.
/**아답터에서사용할 계약자 인터페이스 */
interface MainActivityAdapterContract {

/**아답터뷰*/
    interface View {
     /**리스트 갱신을 위한 데이터 갱신*/
        fun changeData(data: MutableList)
    }

}

5. 계약자 인터페이스 생성.
/**
 * mvp 패턴에서 사용할 계약자 인터페이스 생성.
 * 계약자의 프레젠터를 상속 받음.
 * 등록한 뷰에는 UI처리만 하도록 한다. 화면에 그릴 데이터의 결과값만 던저준다. 
 */
/**mvp 패턴에서 사용할 계약자 인터페이스 생성.*/
interface MainActivityContract {

    /**BaseView 를 상속받은 인터페이스 제네릭으로 인터페이스(Present)를 넘겨줌*/
    interface View : BaseView {
        /**
         * 뷰는 데이터 처리를 하지 않으며 데이터의 결과만 전달한다.
         * 뷰는 프레젠터에서 넘겨받은 결과로 UI의 변경만 한다.
         */
    }

    /**BasePresent를 상속받은 인터페이스 제네릭으로 인터페이스(View)를 넘겨줌*/
    interface Present : BasePresent {
        /**
         * 프레젠터는 데이터를 처리한다.
         * 
         */

        fun attachView(view: View)
        /**뷰 해제.*/
        fun detachView()
        
        /**데이터 갱신위한 아답터뷰 등록*/
        var adapterView: MainActivityAdapterContract.View?
/**데이터 클래스에서 값 가져오기.*/
        fun getData()
        
    }
}

6. 리사이클러뷰 홀더 생성.
/**리사이클러뷰 각 항목 그리기 위한 홀더 생성.*/
class MainActivityViewHolder(override val containerView: View) : RecyclerView.ViewHolder(containerView),
    LayoutContainer {

    companion object {
        fun newInstance(parent: ViewGroup): MainActivityViewHolder {
            val view = LayoutInflater.from(parent.context).inflate(R.layout.datalayout_row, parent, false)
            return MainActivityViewHolder(view)
        }
    }

    fun onBindView(str: String) {
        textView_Row.text = str
    }

}

7. 리사이클러뷰 아답터 
/** 아답터에 대한 MVP */
class MainActivityAdapter : RecyclerView.Adapter(), MainActivityAdapterContract.View {

    private var data: MutableList = mutableListOf()
        private set(value) {
            field = value
            notifyDataSetChanged()
        }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MainActivityViewHolder {
        return MainActivityViewHolder.newInstance(parent)
    }

    override fun getItemCount(): Int {
        return data.size
    }

    override fun onBindViewHolder(holder: MainActivityViewHolder, position: Int) {
        holder.onBindView(data[position])
    }

    override fun changeData(data: MutableList) {
        this.data=data
    }
}

8. 액티비티 구현을 위한 상속 액티비티
/**상속 액티비티*/
abstract class BaseActivity : AppCompatActivity() {

    protected abstract val layoutId: Int

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(layoutId)
    }
}

9. 구현 액티비티 
/**
 * 액티비티가 mvp 패턴에서 View 해당한다. View엔 데이터 처리를 하지않고
 * 데이터 처리를 위한 작업은 presenter에 요청한다.
 */
class MainActivity : BaseActivity(), MainActivityContract.View {


    override val layoutId = R.layout.activity_main

    override val presenter: MainActivityContract.Present = MainActivityPresenter()


    private lateinit var mainActivityAdapter: MainActivityAdapter

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        presenter.attachView(this)

        setupUI()

        presenter.adapterView = mainActivityAdapter

        //프레젠터에 데이터를 요청.
        presenter.getData()
    }

    override fun onDestroy() {
        presenter.detachView()
        super.onDestroy()
    }

    private fun setupUI() {
        setupRecyclerView()
    }

    private fun setupRecyclerView() {
        mainActivityAdapter = MainActivityAdapter()
        recyclerView.adapter = mainActivityAdapter
    }

}

'Android > study' 카테고리의 다른 글

안드로이드 코틀린 프로젝트 디펜던시  (0) 2019.01.25
안드로이드 액티비티 및 프래그먼트.  (0) 2018.09.27
레트로핏, okhttp  (0) 2018.08.27
RxJava  (0) 2018.07.30


/**
 * 리사이클러뷰 아답터를 상속받는 아답터
 * 데이터 초기화.
 */
class CustomAdapter(private val dataSet: Array) :
        RecyclerView.Adapter() {

    /**
     * Provide a reference to the type of views that you are using (custom ViewHolder)
     */
    class ViewHolder(v: View) : RecyclerView.ViewHolder(v) {
        val textView: TextView

        /**홀더 초기화.*/
        init {
            // Define click listener for the ViewHolder's View.
            v.setOnClickListener { Log.d(TAG, "Element $adapterPosition clicked.") }
            textView = v.findViewById(R.id.textView)
        }
    }

    // Create new views (invoked by the layout manager)
    override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): ViewHolder {
        // Create a new view.
        val v = LayoutInflater.from(viewGroup.context)
                .inflate(R.layout.text_row_item, viewGroup, false)

        return ViewHolder(v)
    }

    // Replace the contents of a view (invoked by the layout manager)
    override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) {
        Log.d(TAG, "Element $position set.")

        // Get element from your dataset at this position and replace the contents of the view
        // with that element
        viewHolder.textView.text = dataSet[position]
    }

    // Return the size of your dataset (invoked by the layout manager)
    override fun getItemCount() = dataSet.size

    /**로그켓 사용하는 태그 초기화.*/
    companion object {
        private val TAG = "CustomAdapter"
    }
}



android java

리사이클러뷰 및 리사이클러뷰 아답터, 뷰홀더 정리

안드로이드 샘플

 /**
 * 리스트뷰 생성을 위한 아답터 생성. 리사이클러뷰 아답터 상속 및 뷰홀더 지정.
 */
public class CustomAdapter extends RecyclerView.Adapter {

    /**로그캣 태그*/
    private static final String TAG = "CustomAdapter";
    /**데이터셋 정리*/
    private String[] mDataSet;

    // BEGIN_INCLUDE(recyclerViewSampleViewHolder)
    /**
     * 리사이클러뷰 사용할 뷰홀더 생성 및 상속
     */
    public static class ViewHolder extends RecyclerView.ViewHolder {
    /**텍스트뷰 선언*/
        private final TextView textView;
/**홀더 생성자.*/
        public ViewHolder(View v) {
            super(v);
            /**홀더 클릭리스터 등록.(리스트뷰 클릭)*/
            v.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Log.d(TAG, "Element " + getAdapterPosition() + " clicked.");
                }
            });
            textView = (TextView) v.findViewById(R.id.textView);
        }

        public TextView getTextView() {
            return textView;
        }
    }
    // END_INCLUDE(recyclerViewSampleViewHolder)


    /**
     * Initialize the dataset of the Adapter.
     *
     * @param dataSet String[] containing the data to populate views to be used by RecyclerView.
     * 아답터에 데이터 등록
     */
    public CustomAdapter(String[] dataSet) {
        mDataSet = dataSet;
    }

    // BEGIN_INCLUDE(recyclerViewOnCreateViewHolder)
    // Create new views (invoked by the layout manager)
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
        // Create a new view.
/** 리스트뷰 생성을 위한 뷰 등록 */
        View v = LayoutInflater.from(viewGroup.getContext())
                .inflate(R.layout.text_row_item, viewGroup, false);

        return new ViewHolder(v);
    }
    // END_INCLUDE(recyclerViewOnCreateViewHolder)

    // BEGIN_INCLUDE(recyclerViewOnBindViewHolder)
    // Replace the contents of a view (invoked by the layout manager)
    @Override
    public void onBindViewHolder(ViewHolder viewHolder, final int position) {
        Log.d(TAG, "Element " + position + " set.");

        // Get element from your dataset at this position and replace the contents of the view
        // with that element
/**홀더로 생성된 뷰의 데이터 삽입*/
        viewHolder.getTextView().setText(mDataSet[position]);
    }
    // END_INCLUDE(recyclerViewOnBindViewHolder)

    // Return the size of your dataset (invoked by the layout manager)
    /**데이터의 크기 가져오기.*/
    @Override
    public int getItemCount() {
        return mDataSet.length;
    }
}


Activity 또는 Fragment 에서 


레이아웃 속성 정의.
정의한 데이터를 아답터 생성할때 데이터 삽입.
리사이클러뷰에 아답터 등록.







레트로핏 사용.(java)


안드로이드 프로젝트 생성.


gradle dependencies setting.


app gradle.


dependencies {


    // 인터넷 연결 http 프로토콜

    // https://square.github.io/retrofit/

    // okhttp 를 포함하고 있다.

    implementation 'com.squareup.retrofit2:retrofit:2.5.0'


    // https://github.com/square/retrofit/tree/master/retrofit-converters/gson

    // gson 라이브러리를 포함하고 있다.

    implementation 'com.squareup.retrofit2:converter-gson:2.5.0'


    // http 통신시 로그 보기위한 것.

    // https://github.com/square/okhttp/tree/master/okhttp-logging-interceptor

    // okhttp 를 포함하고 있다.

    implementation 'com.squareup.okhttp3:logging-interceptor:3.10.0'



}

레트로핏을 사용할 기본 조건은 되었고.

레트로핏으로 통신을 할수있는 인터페이스 연결할 클래스 생성.

레트로핏은 http api를 인터페이스 형태로 사용한다.



public class GithubUser {



    private String login;

    private String url;

    private String name;

    private String location;

    private String repos_url;


    public String getLogin() {

        return login;

    }


    public void setLogin(String login) {

        this.login = login;

    }


    public String getUrl() {

        return url;

    }


    public void setUrl(String url) {

        this.url = url;

    }


    public String getName() {

        return name;

    }


    public void setName(String name) {

        this.name = name;

    }


    public String getLocation() {

        return location;

    }


    public void setLocation(String location) {

        this.location = location;

    }


    public String getRepos_url() {

        return repos_url;

    }


    public void setRepos_url(String repos_url) {

        this.repos_url = repos_url;

    }


    @Override

    public String toString() {

        return "login :" + login + ", url :" + url + ", name :" + name + ", location : " + location + ", repos_url :" + repos_url;

    }

}




public class GithubUserRepository {


    private String name;

    private String html_url;

    private String language;


    public String getName() {

        return name;

    }


    public void setName(String name) {

        this.name = name;

    }


    public String getHtml_url() {

        return html_url;

    }


    public void setHtml_url(String html_url) {

        this.html_url = html_url;

    }


    public String getLanguage() {

        return language;

    }


    public void setLanguage(String language) {

        this.language = language;

    }



    @Override

    public String toString() {

        return "name : " + name + ", html_url : " + html_url + ", language : " + language;

    }

}





public interface GithubService {


    @GET("users/{user}")

    Call<GithubUser> getGithubUser(@Path("user") String userName);


    @GET("users/{user}/repos")

    Call<List<GithubUserRepository>> getGithubUserRepository(@Path("user") String userName);

}




ApiConnection 클래스 생성.

실제 통신을 담당할 retrofit 객체를 생성한다.


public class ApiConnection {


    private Retrofit retrofit;


    private final String baseUrl = "https://api.github.com";


    /**

     * 생성자.

     */

    private ApiConnection() {


        OkHttpClient httpClient = new OkHttpClient.Builder()

                .addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))

                .build();


        this.retrofit = new Retrofit.Builder()

                .baseUrl(baseUrl)

                // 내려받는 데이터를 gson 형식으로 데이터 변환

                .addConverterFactory(GsonConverterFactory.create())

                .client(httpClient)

                .build();

    }

        /**

     * 2. 싱글턴 패턴 구현.

     */

    private static final ApiConnection INSTANCE = new ApiConnection();


    public static ApiConnection getInstance() {

        return INSTANCE;

    }


    /**

     * interface  리턴.

     */

    public GithubService getRetrofitService() {

        return retrofit.create(GithubService.class);

    }

}





    MainActivity 에서


    void connection_01() {


        Call<GithubUser> result = ApiConnection.getInstance().getRetrofitService().getGithubUser("bearkinf");


        result.enqueue(new Callback<GithubUser>() {

            @Override

            public void onResponse(Call<GithubUser> call, Response<GithubUser> response) {


                Log.w("LOG","GithubUser : " + response.body());

            }


            @Override

            public void onFailure(Call<GithubUser> call, Throwable t) {


            }

        });

    }



oncreate()에서 함수를 호출하면 깃허브에서 내용을 가져온다.






레트로핏을 이용한 통신 프로젝트에 RxJava 넣기..



라이브러리 추가.



dependencies {

    implementation fileTree(include: ['*.jar'], dir: 'libs')

    implementation 'com.android.support:appcompat-v7:28.0.0'

    implementation 'com.android.support.constraint:constraint-layout:1.1.3'

    implementation 'com.android.support:support-v4:28.0.0'

    testImplementation 'junit:junit:4.12'

    androidTestImplementation 'com.android.support.test:runner:1.0.2'

    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'


    //로그켓 .

    implementation 'com.github.bearkinf:AndroidLogPrintUtil_Java:1.1.1'


    // 인터페이스를 통해 인터넷 연결을 가지고 있다.

    // https://square.github.io/retrofit/

    implementation 'com.squareup.retrofit2:retrofit:2.5.0'

    // https://github.com/square/retrofit/tree/master/retrofit-converters/gson

    implementation 'com.squareup.retrofit2:converter-gson:2.5.0'

    // http 통신시 로그 보기위한 것.

    // https://github.com/square/okhttp/tree/master/okhttp-logging-interceptor

    implementation 'com.squareup.okhttp3:logging-interceptor:3.10.0'


    // Rxjava 타입을 지원한다.

    // https://github.com/square/retrofit/tree/master/retrofit-adapters/rxjava2

    // 자체적으로 RxJava 라이브러리를 가지고 있다.(최신 버전은 아님.)

    // adapter-rxjava2 내부적으로 rxjava를 참조하나, 버그가 수정된 최신버전의 rxjava를 명확히 정의하여 해당 library를 사용하게 하도록한다.

    implementation 'com.squareup.retrofit2:adapter-rxjava2:2.5.0'


    // https://github.com/ReactiveX/RxJava

    // 각각의 라이브러리가 RxJava를 참조하나 최신 라이브러리를 지정한다.

    // rxandroid 내부적으로 rxjava를 참조하나, 버그가 수정된 최신버전의 rxjava를 명확히 정의하여 해당 library를 사용하게 하도록한다.

    implementation "io.reactivex.rxjava2:rxjava:2.2.6"

    // https://github.com/ReactiveX/RxAndroid 스케줄러 관리 (쓰레드 관리

    // 자체적으로 RxJava 라이브러리를 가지고 있다.(최신 버전은 아님.)

    implementation 'io.reactivex.rxjava2:rxandroid:2.1.0'


}




레트로핏 인터페이스에 RxJava 추가.

public interface GithubService {


    @GET("users/{user}")

    Call<GithubUser> getGithubUser(@Path("user") String userName);



    @GET("users/{user}/repos")

    Call<List<GithubUserRepository>> getGithubUserRepository(@Path("user") String userName);



    //RxJava 용 .Observable

    @GET("users/{user}")

    Observable<GithubUser> getGithubUser2(@Path("user") String userName);



    @GET("users/{user}/repos")

    Flowable<List<GithubUserRepository>> getGithubUserRepository2(@Path("user") String userName);


}



레트로핏 객체에 RxJava 를 사용하기 위해 아답터 추가.


public class ApiConnection {


    private Retrofit retrofit;


    private final String baseUrl = "https://api.github.com";


    /**

     * 생성자.

     */

    private ApiConnection() {


        OkHttpClient httpClient = new OkHttpClient.Builder()

                .addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))

                .build();


        this.retrofit = new Retrofit.Builder()

                .baseUrl(baseUrl)

                // 내려받는 데이터를 gson 형식으로 데이터 변환

                .addConverterFactory(GsonConverterFactory.create())

                // RxJava 를 사용하게되면 해당 아답터팩토리를 등록해야 한다.

                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())


                .client(httpClient)

                .build();

    }

        /**

     * 2. 싱글턴 패턴 구현.

     */

    private static final ApiConnection INSTANCE = new ApiConnection();


    public static ApiConnection getInstance() {

        return INSTANCE;

    }


    /**

     * interface  리턴.

     */

    public GithubService getRetrofitService() {

        return retrofit.create(GithubService.class);

    }

}


MainActivity에서 RxJava를 이용한 레트로핏 통신 코드 넣기.



    void connection_03() {


        /**

         * 람다식으로 사용을하려면 .

         *   compileOptions {

         *         sourceCompatibility JavaVersion.VERSION_1_8

         *         targetCompatibility JavaVersion.VERSION_1_8

         *   }

         *   넣어 주어야 한다.

         */

        LogPrintUtil.w("connection_03 start");

        ApiConnection.getInstance().getRetrofitService()

                .getGithubUser2("bearkinf")

                .subscribeOn(Schedulers.io())

                .observeOn(AndroidSchedulers.mainThread())

                .subscribe(githubUser -> {

                            LogPrintUtil.w("Observable    Data :" + githubUser);

                        }, throwable -> {


                        }

                );

    }


oncreate()에서 함수를 호출하면 깃허브에서 내용을 가져온다.




코틀린 버전은 코틀린 탭에서. 다시 작성.





코틀린 프로잭트 생성.


레트로핏 인터페이스 생성.

interface GithubService {



    @GET("users/{user}")

    fun getGithubUser(@Path("user") userName: String): Call<GithubUser>



    @GET("users/{user}/repos")

    fun getgithubUserRepository(@Path("user") userName: String): Observable<List<GithubUserRepository>>


}


레트로핏 객체 클래스 생성.

/**스테틱 클래스 생성.*/

object ApiConnection {


    private val BASE_URL = "https://api.gitHub.com"


    private val retrofit by lazy {

        val httpClient = OkHttpClient.Builder()

            .addInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))

            .build()


        Retrofit.Builder()

            .baseUrl(BASE_URL)

            .addConverterFactory(GsonConverterFactory.create())

            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())

            .client(httpClient)

            .build()

    }

    val getRetrofitService = retrofit.create(GithubService::class.java)

}


MainActivity 에서 oncreate 에 함수 적용.

    private fun retrofitConnection_01() {


        val getGithubUser = ApiConnection.getRetrofitService.getGithubUser("bearkinf")


        getGithubUser.enqueue(object : Callback<GithubUser> {


            override fun onFailure(call: Call<GithubUser>, t: Throwable) {

            }


            override fun onResponse(call: Call<GithubUser>, response: Response<GithubUser>) {


                LogPrintUtil.w("response : ${response.body()}")


            }

        })

    }


    private fun retrofitConnection_02() {



        ApiConnection.getRetrofitService

            .getgithubUserRepository("bearkinf")

            .subscribeOn(Schedulers.io())

            .observeOn(AndroidSchedulers.mainThread())


            .subscribe({


                LogPrintUtil.w("RxJava : $it")


            }, {


            })



    }





'Kotlin > study' 카테고리의 다른 글

isNullOrBlank or isNullOrEmpty  (0) 2018.11.19
코틀린 클래스.  (0) 2018.10.04
코틀린 apply,let 함수  (0) 2018.08.24



레트로핏 사용.(java)


안드로이드 프로젝트 생성.


gradle dependencies setting.


app gradle.


dependencies {


    // 인터넷 연결 http 프로토콜

    // https://square.github.io/retrofit/

    // okhttp 를 포함하고 있다.

    implementation 'com.squareup.retrofit2:retrofit:2.5.0'


    // https://github.com/square/retrofit/tree/master/retrofit-converters/gson

    // gson 라이브러리를 포함하고 있다.

    implementation 'com.squareup.retrofit2:converter-gson:2.5.0'


    // http 통신시 로그 보기위한 것.

    // https://github.com/square/okhttp/tree/master/okhttp-logging-interceptor

    // okhttp 를 포함하고 있다.

    implementation 'com.squareup.okhttp3:logging-interceptor:3.10.0'



}

레트로핏을 사용할 기본 조건은 되었고.

레트로핏으로 통신을 할수있는 인터페이스 연결할 클래스 생성.

레트로핏은 http api를 인터페이스 형태로 사용한다.



public class GithubUser {



    private String login;

    private String url;

    private String name;

    private String location;

    private String repos_url;


    public String getLogin() {

        return login;

    }


    public void setLogin(String login) {

        this.login = login;

    }


    public String getUrl() {

        return url;

    }


    public void setUrl(String url) {

        this.url = url;

    }


    public String getName() {

        return name;

    }


    public void setName(String name) {

        this.name = name;

    }


    public String getLocation() {

        return location;

    }


    public void setLocation(String location) {

        this.location = location;

    }


    public String getRepos_url() {

        return repos_url;

    }


    public void setRepos_url(String repos_url) {

        this.repos_url = repos_url;

    }


    @Override

    public String toString() {

        return "login :" + login + ", url :" + url + ", name :" + name + ", location : " + location + ", repos_url :" + repos_url;

    }

}




public class GithubUserRepository {


    private String name;

    private String html_url;

    private String language;


    public String getName() {

        return name;

    }


    public void setName(String name) {

        this.name = name;

    }


    public String getHtml_url() {

        return html_url;

    }


    public void setHtml_url(String html_url) {

        this.html_url = html_url;

    }


    public String getLanguage() {

        return language;

    }


    public void setLanguage(String language) {

        this.language = language;

    }



    @Override

    public String toString() {

        return "name : " + name + ", html_url : " + html_url + ", language : " + language;

    }

}





public interface GithubService {


    @GET("users/{user}")

    Call<GithubUser> getGithubUser(@Path("user") String userName);


    @GET("users/{user}/repos")

    Call<List<GithubUserRepository>> getGithubUserRepository(@Path("user") String userName);

}




ApiConnection 클래스 생성.

실제 통신을 담당할 retrofit 객체를 생성한다.


public class ApiConnection {


    private Retrofit retrofit;


    private final String baseUrl = "https://api.github.com";


    /**

     * 생성자.

     */

    private ApiConnection() {


        OkHttpClient httpClient = new OkHttpClient.Builder()

                .addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))

                .build();


        this.retrofit = new Retrofit.Builder()

                .baseUrl(baseUrl)

                // 내려받는 데이터를 gson 형식으로 데이터 변환

                .addConverterFactory(GsonConverterFactory.create())

                .client(httpClient)

                .build();

    }

        /**

     * 2. 싱글턴 패턴 구현.

     */

    private static final ApiConnection INSTANCE = new ApiConnection();


    public static ApiConnection getInstance() {

        return INSTANCE;

    }


    /**

     * interface  리턴.

     */

    public GithubService getRetrofitService() {

        return retrofit.create(GithubService.class);

    }

}





    MainActivity 에서


    void connection_01() {


        Call<GithubUser> result = ApiConnection.getInstance().getRetrofitService().getGithubUser("bearkinf");


        result.enqueue(new Callback<GithubUser>() {

            @Override

            public void onResponse(Call<GithubUser> call, Response<GithubUser> response) {


                Log.w("LOG","GithubUser : " + response.body());

            }


            @Override

            public void onFailure(Call<GithubUser> call, Throwable t) {


            }

        });

    }



oncreate()에서 함수를 호출하면 깃허브에서 내용을 가져온다.






레트로핏을 이용한 통신 프로젝트에 RxJava 넣기..



라이브러리 추가.



dependencies {

    implementation fileTree(include: ['*.jar'], dir: 'libs')

    implementation 'com.android.support:appcompat-v7:28.0.0'

    implementation 'com.android.support.constraint:constraint-layout:1.1.3'

    implementation 'com.android.support:support-v4:28.0.0'

    testImplementation 'junit:junit:4.12'

    androidTestImplementation 'com.android.support.test:runner:1.0.2'

    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'


    //로그켓 .

    implementation 'com.github.bearkinf:AndroidLogPrintUtil_Java:1.1.1'


    // 인터페이스를 통해 인터넷 연결을 가지고 있다.

    // https://square.github.io/retrofit/

    implementation 'com.squareup.retrofit2:retrofit:2.5.0'

    // https://github.com/square/retrofit/tree/master/retrofit-converters/gson

    implementation 'com.squareup.retrofit2:converter-gson:2.5.0'

    // http 통신시 로그 보기위한 것.

    // https://github.com/square/okhttp/tree/master/okhttp-logging-interceptor

    implementation 'com.squareup.okhttp3:logging-interceptor:3.10.0'


    // Rxjava 타입을 지원한다.

    // https://github.com/square/retrofit/tree/master/retrofit-adapters/rxjava2

    // 자체적으로 RxJava 라이브러리를 가지고 있다.(최신 버전은 아님.)

    // adapter-rxjava2 내부적으로 rxjava를 참조하나, 버그가 수정된 최신버전의 rxjava를 명확히 정의하여 해당 library를 사용하게 하도록한다.

    implementation 'com.squareup.retrofit2:adapter-rxjava2:2.5.0'


    // https://github.com/ReactiveX/RxJava

    // 각각의 라이브러리가 RxJava를 참조하나 최신 라이브러리를 지정한다.

    // rxandroid 내부적으로 rxjava를 참조하나, 버그가 수정된 최신버전의 rxjava를 명확히 정의하여 해당 library를 사용하게 하도록한다.

    implementation "io.reactivex.rxjava2:rxjava:2.2.6"

    // https://github.com/ReactiveX/RxAndroid 스케줄러 관리 (쓰레드 관리

    // 자체적으로 RxJava 라이브러리를 가지고 있다.(최신 버전은 아님.)

    implementation 'io.reactivex.rxjava2:rxandroid:2.1.0'


}




레트로핏 인터페이스에 RxJava 추가.

public interface GithubService {


    @GET("users/{user}")

    Call<GithubUser> getGithubUser(@Path("user") String userName);



    @GET("users/{user}/repos")

    Call<List<GithubUserRepository>> getGithubUserRepository(@Path("user") String userName);



    //RxJava 용 .Observable

    @GET("users/{user}")

    Observable<GithubUser> getGithubUser2(@Path("user") String userName);



    @GET("users/{user}/repos")

    Flowable<List<GithubUserRepository>> getGithubUserRepository2(@Path("user") String userName);


}



레트로핏 객체에 RxJava 를 사용하기 위해 아답터 추가.


public class ApiConnection {


    private Retrofit retrofit;


    private final String baseUrl = "https://api.github.com";


    /**

     * 생성자.

     */

    private ApiConnection() {


        OkHttpClient httpClient = new OkHttpClient.Builder()

                .addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))

                .build();


        this.retrofit = new Retrofit.Builder()

                .baseUrl(baseUrl)

                // 내려받는 데이터를 gson 형식으로 데이터 변환

                .addConverterFactory(GsonConverterFactory.create())

                // RxJava 를 사용하게되면 해당 아답터팩토리를 등록해야 한다.

                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())


                .client(httpClient)

                .build();

    }

        /**

     * 2. 싱글턴 패턴 구현.

     */

    private static final ApiConnection INSTANCE = new ApiConnection();


    public static ApiConnection getInstance() {

        return INSTANCE;

    }


    /**

     * interface  리턴.

     */

    public GithubService getRetrofitService() {

        return retrofit.create(GithubService.class);

    }

}


MainActivity에서 RxJava를 이용한 레트로핏 통신 코드 넣기.



    void connection_03() {


        /**

         * 람다식으로 사용을하려면 .

         *   compileOptions {

         *         sourceCompatibility JavaVersion.VERSION_1_8

         *         targetCompatibility JavaVersion.VERSION_1_8

         *   }

         *   넣어 주어야 한다.

         */

        LogPrintUtil.w("connection_03 start");

        ApiConnection.getInstance().getRetrofitService()

                .getGithubUser2("bearkinf")

                .subscribeOn(Schedulers.io())

                .observeOn(AndroidSchedulers.mainThread())

                .subscribe(githubUser -> {

                            LogPrintUtil.w("Observable    Data :" + githubUser);

                        }, throwable -> {


                        }

                );

    }


oncreate()에서 함수를 호출하면 깃허브에서 내용을 가져온다.




코틀린 버전은 코틀린 탭에서. 다시 작성.





코틀린 프로잭트 생성.


레트로핏 인터페이스 생성.

interface GithubService {



    @GET("users/{user}")

    fun getGithubUser(@Path("user") userName: String): Call<GithubUser>



    @GET("users/{user}/repos")

    fun getgithubUserRepository(@Path("user") userName: String): Observable<List<GithubUserRepository>>


}


레트로핏 객체 클래스 생성.

/**스테틱 클래스 생성.*/

object ApiConnection {


    private val BASE_URL = "https://api.gitHub.com"


    private val retrofit by lazy {

        val httpClient = OkHttpClient.Builder()

            .addInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))

            .build()


        Retrofit.Builder()

            .baseUrl(BASE_URL)

            .addConverterFactory(GsonConverterFactory.create())

            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())

            .client(httpClient)

            .build()

    }

    val getRetrofitService = retrofit.create(GithubService::class.java)

}


MainActivity 에서 oncreate 에 함수 적용.

    private fun retrofitConnection_01() {


        val getGithubUser = ApiConnection.getRetrofitService.getGithubUser("bearkinf")


        getGithubUser.enqueue(object : Callback<GithubUser> {


            override fun onFailure(call: Call<GithubUser>, t: Throwable) {

            }


            override fun onResponse(call: Call<GithubUser>, response: Response<GithubUser>) {


                LogPrintUtil.w("response : ${response.body()}")


            }

        })

    }


    private fun retrofitConnection_02() {



        ApiConnection.getRetrofitService

            .getgithubUserRepository("bearkinf")

            .subscribeOn(Schedulers.io())

            .observeOn(AndroidSchedulers.mainThread())


            .subscribe({


                LogPrintUtil.w("RxJava : $it")


            }, {


            })



    }





'Java > study' 카테고리의 다른 글

자바 제네릭  (0) 2018.09.18
자바 분기문(break, continue)  (0) 2018.08.14
자바 반복문  (0) 2018.08.09
자바 제어문  (0) 2018.08.03
자바 자료형 종류  (0) 2018.07.26


안드로이드 코틀린 프로젝트.


안드로이드 targetSdkVersion 26(Oreo[8.0]) 이상으로 설정해야한다.(정책)


//코틀린 추가 확장(안드로이드 리사이클러뷰 뷰홀더에 사용함 LayoutContainer 구현.)

androidExtensions {

    experimental = true

}




안드로이드 프로젝트에서 자주 사용하는 라이브러리 정리



안드로이드 라이브러리.

Project Structure 에서 Dependencies 선택 후 Library Dependency 클릭하여 라이브러리 추가.(타겟버전에 맞추어 추가함.)



통신관련 라이브러리.


* 레트로핏 : 안드로이드 통신 라이브러리.

// 인터페이스를 통해 인터넷 연결을 가지고 있다.

// https://square.github.io/retrofit/

implementation 'com.squareup.retrofit2:retrofit:2.5.0'

   

/*레트로핏 지원 라이브러리*/    

// jsonData 형식을 클래스 객체형식으로 변환하여 준다.

// https://github.com/square/retrofit/tree/master/retrofit-converters/gson

implementation 'com.squareup.retrofit2:converter-gson:latest.version'


// Rxjava 타입을 지원한다.

// https://github.com/square/retrofit/tree/master/retrofit-adapters/rxjava2

implementation 'com.squareup.retrofit2:adapter-rxjava2:latest.version'

   

* okhttp : 안드로이드 통신 라이브러리.(레트포핏을 사용하면 okhttp 최신 버전이 들어있다)

// http,http2 통신라이브러리

// https://square.github.io/okhttp/ 

implementation 'com.squareup.okhttp3:okhttp:3.12.1'

// http 통신시 로그 보기위한 것.

// https://github.com/square/okhttp/tree/master/okhttp-logging-interceptor 

implementation 'com.squareup.okhttp3:logging-interceptor:(insert latest version)'



* Gson : 안드로이드 json 파싱 라이브러리.

// 객체 형태로 데이터를 만들어 준다.

implementation 'com.google.code.gson:gson:2.8.5'




프로그래밍 라이브러리.

// binding :제본   bind : 묶다 


RxJava

– Reactive Extensions for the JVM – a library for composing asynchronous and event-based programs using observable sequences for the Java VM.

* RxJava : 반응형 프로그래밍 라이브러리

   // https://github.com/ReactiveX/RxJava

   implementation "io.reactivex.rxjava2:rxjava:2.x.y"


/*

* RxKotlin 과 RxAndroid 는 내부적으로 RxJava를 참조하나 최신 버전의 RxJava를 명확하게 정의하여 해당 라이브러리를 쓰도록 한다.

*/


RxKotlin

RxJava bindings for Kotlin(기본적으로 RxJava 를 가지고 있다.)

* RxKotlin :    안드로이드 코틀린에서 확장지원 라이브러리.(RxJava가 있어야 하며 버전에 맞게 설정해야한다.)

        // 안드로이드 프로젝트라면. RxAndroid 설정후 .

        // https://github.com/ReactiveX/RxKotlin

        implementation 'io.reactivex.rxjava2:rxkotlin:x.y.z'


RxAndroid

RxJava bindings for Android(기본적으로 RxJava 를 가지고 있다.)

* RxAndroid :  안드로이드 프로젝트에서 사용하기 위한 라이브러리.(RxJava가 있어야 한다.) 쓰레드 관련한 모듈을 제공한다.

       // https://github.com/ReactiveX/RxAndroid

       implementation 'io.reactivex.rxjava2:rxandroid:2.1.0'

       // Because RxAndroid releases are few and far between, it is recommended you also

       // explicitly depend on RxJava's latest version for bug fixes and new features.

       // (see https://github.com/ReactiveX/RxJava/releases for latest 2.x.x version)

       implementation 'io.reactivex.rxjava2:rxjava:2.x.x'

       

* RxBinding 를 사용하기 위한 추가 지원 라이브러리들.

//RxBinding : RxJava binding APIs for Android UI widgets from the platform and support libraries.

implementation 'com.jakewharton.rxbinding3:rxbinding:3.0.0-alpha2'

//

implementation 'com.jakewharton.rxbinding2:rxbinding-kotlin:2.1.0'

implementation 'com.jakewharton.rxbinding2:rxbinding-support-v4-kotlin:2.1.0'

implementation 'com.jakewharton.rxbinding2:rxbinding-appcompat-v7-kotlin:2.1.0'

implementation 'com.jakewharton.rxbinding2:rxbinding-design-kotlin:2.1.0'

implementation 'com.jakewharton.rxbinding2:rxbinding-recyclerview-v7-kotlin:2.1.0'

*RxPermission : 안드로이드 권한 라이브러리

//https://github.com/tbruyelle/RxPermissions

implementation 'com.tbruyelle.rxpermissions2:rxpermissions:0.9.5@aar'


* RxLifecycle : RxJava를 사용하면서 subscribe를 해제 하지 않으면 메모리릭이 발생될수도있기에 서브스크라이브 종료를 해주는 라이브러리.

// https://github.com/trello/RxLifecycle

implementation 'com.trello.rxlifecycle3:rxlifecycle:3.0.0'


// If you want to bind to Android-specific lifecycles

implementation 'com.trello.rxlifecycle3:rxlifecycle-android:3.0.0'


// If you want pre-written Activities and Fragments you can subclass as providers

implementation 'com.trello.rxlifecycle3:rxlifecycle-components:3.0.0'


// If you want pre-written support preference Fragments you can subclass as providers

implementation 'com.trello.rxlifecycle3:rxlifecycle-components-preference:3.0.0'


// If you want to use Android Lifecycle for providers

implementation 'com.trello.rxlifecycle3:rxlifecycle-android-lifecycle:3.0.0'


// If you want to use Kotlin syntax

implementation 'com.trello.rxlifecycle3:rxlifecycle-kotlin:3.0.0'


// If you want to use Kotlin syntax with Android Lifecycle

implementation 'com.trello.rxlifecycle3:rxlifecycle-android-lifecycle-kotlin:3.0.0'


// If you want to use Navi for providers

// DEPRECATED: Use rxlifecycle-android-lifecycle instead. This will be removed in a future release.

implementation 'com.trello.rxlifecycle3:rxlifecycle-navi:3.0.0'





추가지원 라이브러리.

* Realm : 객체중심의 데이터베이스 라이브러리.

// https://realm.io/docs/java/latest


* glide : 이미지 로딩 라이브러리

   repositories {

       mavenCentral()

     google()

           }


     dependencies {

     implementation 'com.github.bumptech.glide:glide:4.8.0'

     annotationProcessor 'com.github.bumptech.glide:compiler:4.8.0'

     }


'Android > study' 카테고리의 다른 글

MVP 패턴  (0) 2019.04.25
안드로이드 액티비티 및 프래그먼트.  (0) 2018.09.27
레트로핏, okhttp  (0) 2018.08.27
RxJava  (0) 2018.07.30


코틀린 isNullOrBlank or isNullOrEmpty 테스트.


// 널 을 가지고 있는 스트링.
var nullString: String? = null

//공백체크.
println(nullString.isNullOrBlank()?.toString()) //output: true
//비어있는
println(nullString.isNullOrEmpty()?.toString()) //output: true

// 데이터를 가지고 잇는 스트링.
var helloString: String = "Hello"
println(helloString.isNullOrBlank()?.toString()) //output: false
println(helloString.isNullOrEmpty()?.toString()) //output: false

// 빈 문자열을 가지고 있는 스트링.
var blankString: String = ""
println(blankString.isNullOrBlank()?.toString()) //output: true
println(blankString.isNullOrEmpty()?.toString()) //output: true

// 공백을 가지고 있는 스트링.
var emptyString: String = " "
println(emptyString.isNullOrBlank()?.toString()) //output: true
println(emptyString.isNullOrEmpty()?.toString()) //output: false

// 공백을 가지고 있는 스트링.
var emptyString2: String = " ㅇㅇㅇ"
println(emptyString2.isNullOrBlank()?.toString()) //output: false
println(emptyString2.isNullOrEmpty()?.toString()) //output: false


'Kotlin > study' 카테고리의 다른 글

Retrofit, RxJava, AndroidProject  (0) 2019.01.30
코틀린 클래스.  (0) 2018.10.04
코틀린 apply,let 함수  (0) 2018.08.24

TabLayout _ 코틀린




탭레이아웃 사용하기


탭레이아웃을 사용하기 위한 디펜던시 추가.


프로젝트 생성 후 build.gradle(app) 아래 코드를 추가.


dependencies {

...

...

implementation 'com.android.support:design:x.y.z //추가.

}



3개의 프래그먼트를 뵤여주기 위해 탭 레이아웃 과 뷰페이저를 xml에 등록함.

//////////////////////////////////////////////////////////////////////////////////////////

xml 소스 구성.

activity_main.xml


상단 

//////////////////////////////////////////////////////////////////////////////////////////

<?xml version="1.0" encoding="utf-8"?>

<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"

    xmlns:app="http://schemas.android.com/apk/res-auto"

    xmlns:tools="http://schemas.android.com/tools"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    tools:context=".activity.MainActivity">


    <android.support.design.widget.TabLayout


        android:id="@+id/tabLayout"

        android:layout_width="match_parent"

        android:layout_height="?android:attr/actionBarSize"

        app:layout_constraintBottom_toTopOf="@+id/viewPager"

        app:layout_constraintLeft_toLeftOf="parent"

        app:layout_constraintRight_toRightOf="parent"


        app:layout_constraintTop_toTopOf="parent"


        >


    </android.support.design.widget.TabLayout>



    <android.support.v4.view.ViewPager

        android:id="@+id/viewPager"

        android:layout_width="match_parent"

        android:layout_height="0dp"


        app:layout_constraintBottom_toBottomOf="parent"

        app:layout_constraintLeft_toLeftOf="parent"

        app:layout_constraintRight_toRightOf="parent"

        app:layout_constraintTop_toBottomOf="@+id/tabLayout">


    </android.support.v4.view.ViewPager>



</android.support.constraint.ConstraintLayout>

//////////////////////////////////////////////////////////////////////////////////////////


하단

//////////////////////////////////////////////////////////////////////////////////////////

<?xml version="1.0" encoding="utf-8"?>

<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"

    xmlns:app="http://schemas.android.com/apk/res-auto"

    xmlns:tools="http://schemas.android.com/tools"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    tools:context=".MainActivity">

    

    <android.support.v4.view.ViewPager

        android:id="@+id/viewPager"

        android:layout_width="match_parent"

        android:layout_height="0dp"

        app:layout_constraintBottom_toTopOf="@+id/tabLayout"

        app:layout_constraintLeft_toLeftOf="parent"

        app:layout_constraintRight_toRightOf="parent"

        app:layout_constraintTop_toTopOf="parent">

    </android.support.v4.view.ViewPager>


    <android.support.design.widget.TabLayout

        android:id="@+id/tabLayout"

        android:layout_width="match_parent"

        android:layout_height="?android:attr/actionBarSize"

        app:layout_constraintBottom_toBottomOf="parent"

        app:layout_constraintLeft_toLeftOf="parent"

        app:layout_constraintRight_toRightOf="parent"

        app:layout_constraintTop_toBottomOf="@+id/viewPager">

    </android.support.design.widget.TabLayout>


</android.support.constraint.ConstraintLayout>

//////////////////////////////////////////////////////////////////////////////////////////


뷰 페이저 안에 탭 레이아웃 포함.(상단.)

//////////////////////////////////////////////////////////////////////////////////////////

<?xml version="1.0" encoding="utf-8"?>

<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"

    xmlns:app="http://schemas.android.com/apk/res-auto"

    xmlns:tools="http://schemas.android.com/tools"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    tools:context=".activity.MainActivity">



    <android.support.v4.view.ViewPager

        android:id="@+id/viewPager"

        android:layout_width="match_parent"

        android:layout_height="match_parent"

        app:layout_constraintBottom_toBottomOf="parent"

        app:layout_constraintLeft_toLeftOf="parent"

        app:layout_constraintRight_toRightOf="parent"

        app:layout_constraintTop_toTopOf="parent">



        <android.support.design.widget.TabLayout


            android:id="@+id/tabLayout"

            android:layout_width="match_parent"

            android:layout_height="?android:attr/actionBarSize">


        </android.support.design.widget.TabLayout>



    </android.support.v4.view.ViewPager>




//////////////////////////////////////////////////////////////////////////////////////////



MainActivity.kt 소스 작성.

탭레이아웃을 구성하기 위한 ui 정의 및 프래그먼트 데이터 생성.


class MainActivity : AppCompatActivity() {


    override fun onCreate(savedInstanceState: Bundle?) {

        super.onCreate(savedInstanceState)

        setContentView(R.layout.activity_main)


        setupUI()

    }


    //UI 초기화.

    private fun setupUI() {


        setupTabLayout()

    }


    // 탭 레이아웃 설정.

    private fun setupTabLayout() {


        val pageAdapter = MainViewPagerAdapter(setFragmentList(), supportFragmentManager)

        viewPager.adapter = pageAdapter


        tabLayout.setupWithViewPager(viewPager)


    }


    // 프래그먼트 리스트 설정.

    private fun setFragmentList(): List<Pair<Fragment, String>> {

//        val pageList = listOf(

//            Pair(MainFragment_1.newInstance(), "first"),

//            Pair(MainFragment_2.newInstance(), "first"),

//            Pair(MainFragment_3.newInstance(), "first")

//        )

//        return pageList


        return listOf(

            Pair(MainFragment_1.newInstance(), "first"),

            Pair(MainFragment_2.newInstance(), "second"),

            Pair(MainFragment_3.newInstance(), "third")

        )

    }


    // 프래그먼트 리스트 설정.

    private fun setFragmentList2() = listOf(

        Pair(MainFragment_1.newInstance(), "first"),

        Pair(MainFragment_2.newInstance(), "second"),

        Pair(MainFragment_3.newInstance(), "third")

    )


}

//////////////////////////////////////////////////////////////////////////////////////////

ViewPagerAdapter 소스(FragmentPagerAdapter)


class MainViewPagerAdapter(val pageList: List<Pair<Fragment, String>>, fragmentManager: FragmentManager) :

    FragmentPagerAdapter(fragmentManager) {



    override fun getItem(position: Int): Fragment {

        return pageList[position].first

    }


    override fun getCount(): Int {

        return pageList.size

    }


    override fun getPageTitle(position: Int): CharSequence? {

//        return super.getPageTitle(position)

        return pageList[position].second

    }


}

//////////////////////////////////////////////////////////////////////////////////////////


보여줄 프래그먼트 소스.



private const val ARG_PARAM1 = "param1"

private const val ARG_PARAM2 = "param2"



class MainFragment_1 : Fragment() {


    private var param1: String? = null

    private var param2: String? = null


    override fun onCreate(savedInstanceState: Bundle?) {

        super.onCreate(savedInstanceState)

        arguments?.let {

            param1 = it.getString(ARG_PARAM1)

            param2 = it.getString(ARG_PARAM2)

        }

    }


    override fun onCreateView(

        inflater: LayoutInflater, container: ViewGroup?,

        savedInstanceState: Bundle?

    ): View? {


        return inflater.inflate(R.layout.fragment_main_fragment_1, container, false)

    }


    companion object {

        // param을 null로 처리하면 인자를 따로 추가 안해도 된다.

        // 인자값을 추가할 경우 해당 데이터가 저장된다.

        @JvmStatic

        fun newInstance(param1: String? = null, param2: String? = null) =

            MainFragment_1().apply {

                arguments = Bundle().apply {

                    putString(ARG_PARAM1, param1)

                    putString(ARG_PARAM2, param2)

                }

            }

    }

}


//////////////////////////////////////////////////////////////////////////////////////////

탭 레이아웃 기본 정리





















코디네이터레이아웃 사용해서 스크롤시 

툴바 및 리사이클러뷰 스크롤시 최상단 및 최하단 터치 감지가 불량일 때가 있다.

최상단 혹은 최하단 스크롤 후 리스트 항목을 클릭이 되지 않아 두번 클릭해야하는데 


안드로이드 sdk 28에서는 정상동작 한다.

이전 버전에서 AppBarLayout.Behavior 에 버그가 있는듯.



android coordinatorlayout recyclerview scroll click

이렇게 검색하니 스택오버플로우에 올라온 글

Click not working on RecyclerView in CoordinatorLayout when scrolling



코틀린 코드만 입력


게시글 중 해당 링크가 있고 수정된 코드 java와 kotlin이 있음.


https://gist.github.com/erikhuizinga/edf408167b46eb5b1568424563ca4e59


kotlin

//////////////////////////////////////////////////////////////////////////////////////////

/**

 * Workaround AppBarLayout.Behavior for https://issuetracker.google.com/66996774

 *

 *

 * See https://gist.github.com/chrisbanes/8391b5adb9ee42180893300850ed02f2 for

 * example usage.

 *

 * Kotlinised by Erik Huizinga (github: @erikhuizinga).

 */

class FixAppBarLayoutBehavior(context: Context?, attrs: AttributeSet?) :

AppBarLayout.Behavior(context, attrs) {


override fun onNestedScroll(coordinatorLayout: CoordinatorLayout, child: AppBarLayout,

                            target: View, dxConsumed: Int, dyConsumed: Int, dxUnconsumed: Int,

                            dyUnconsumed: Int, type: Int) {

super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed,

dyUnconsumed, type)

stopNestedScrollIfNeeded(dyUnconsumed, child, target, type)

}


override fun onNestedPreScroll(coordinatorLayout: CoordinatorLayout, child: AppBarLayout,

                               target: View, dx: Int, dy: Int, consumed: IntArray, type: Int) {

super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed, type)

stopNestedScrollIfNeeded(dy, child, target, type)

}


private fun stopNestedScrollIfNeeded(dy: Int, child: AppBarLayout, target: View, type: Int) {

if (type == ViewCompat.TYPE_NON_TOUCH) {

val currOffset = topAndBottomOffset

if (dy < 0 && currOffset == 0 || dy > 0 && currOffset == -child.totalScrollRange) {

ViewCompat.stopNestedScroll(target, ViewCompat.TYPE_NON_TOUCH)

}

}

}

}

//////////////////////////////////////////////////////////////////////////////////////////


코드 사용법 

AppBarLayout abl = findViewById(R.id.app_bar);

((CoordinatorLayout.LayoutParams) abl.getLayoutParams()).setBehavior(new FixAppBarLayoutBehavior());



xml 사용법

<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"

        xmlns:app="http://schemas.android.com/apk/res-auto"

        android:layout_width="match_parent"

        android:layout_height="match_parent">


    <android.support.design.widget.AppBarLayout

            android:id="@+id/app_bar"

            android:layout_height="..."

            android:layout_width="..."

            app:layout_behavior="your.package.FixAppBarLayoutBehavior">


    </android.support.design.widget.AppBarLayout>


    <!-- Content -->


</android.support.design.widget.CoordinatorLayout>






+ Recent posts