google android official doc 기본설명

https://developer.android.com/topic/libraries/architecture/livedata

LiveData with coroutines – official doc

https://developer.android.com/topic/libraries/architecture/coroutines#livedata

When using LiveData, you might need to calculate values asynchronously. For example, you might want to retrieve a user’s preferences and serve them to your UI. In these cases, you can use the liveData builder function to call a suspend function, serving the result as a LiveData object.

val user: LiveData<User> = liveData {
   val data = database.loadUser() // loadUser is a suspend function.
   emit(data)
}

emit() 과 emitSource()의 차이점

https://stackoverflow.com/a/58950866/3151712

original source : https://youtu.be/-Lha9n8VJf0

예제 코드: https://resocoder.com/2018/06/01/kotlin-apply-let-run-with-also-higher-order-standard-functions/

also, let은 {}안에서 it으로 접근가능하다. 

apply, also 는 들어온 obj를 처리한후 같은 종류의 obj를 리턴한다. 

original source : https://youtu.be/ArSOSm1P9do

thread , coroutines에 대해 굉장히 쉽게 자세하게 알려준다. 45분분량

위 그림은 용어 설명이다. 

코루틴을 사용해 특정 루틴의 블로킹을 방지하고 비동기적 협력형 멀티태스크를 구현할수 있게 된다.

.

.

위그림은 각 루틴들이 지연되면서 순차처리하므로 시간은 순차처리하는 것과 같은 시간이 걸렸다.

.

.

위그림은 동시성을 구현해서 시간이 줄어들었다.

.

.

코루틴은 멀티스레드를 이용할수도 있지만 특별히 지정하지 않으면 하나의 스레드를이용한다. 위의 경우 하나의 스레드에서 돌아가는 두 루틴이 있는데 스레드 자체를 지연해서 처리속도가 느려졌다.

.

.

original source : https://medium.com/tompee/idiomatic-kotlin-lambdas-and-sam-constructors-fe2075965bfb

This article is a part of the Idiomatic Kotlin series. The complete list is at the bottom of the article.

In this article we will explore Kotlin lambdas, SAM constructors and interoperability with Java functional interfaces. For those who are not familiar with functional programming, lambdas and functional interfaces in Java, this might not be the best entry point for you but I will try to explain as easy as possible.

What is a Lambda expression?

A lambda expression is a block of code that can be passed to another function. Functions that accept these types of functions are normally called Higher-order functions. Lambda expressions allows us to realize Functional Programming, a paradigm wherein functions are treated as values.

Before Java 8, this is achieved using anonymous inner classes. Let us look at an example.

button.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        return false;
    }
});

To achieve behavior passing, you need to create an instance of the interface and pass it to the function.

Java 8 introduced lambda expressions along with functional interfaces. A functional interface is an interface with a single method. They are commonly referred to as single abstract method or SAM. Lambda expressions represents these functional interfaces in a more concise way to deal with functional programming. Converting the above code to lambda syntax will look like

button.setOnTouchListener((v, event) -> false);

Plain and simple. Kotlin has a similar syntax for lambdas. We will discuss that in the next sections.

Motivation

Aside from conciseness, syntactic sugar and reduction of boilerplate code, there are other benefits to using lambdas as well. Lambda functions, if not capturing, each exists as a single object in the JVM and reusing them will not incur any other performance overhead. They are also generated at runtime while anonymous inner classes are class-loaded and instantiated for each call.

How to define a lambda function?

The most concise syntax for a kotlin lambda function is

{ param1 : Type1, param2 : Type2 -> body }

Specific rules to follow:

  1. Always enclosed in curly braces
  2. Left part consists of comma separated parameters. No need to enclose in parentheses. The arrow serves as the separator.
  3. The right side is the code body. This can be multi-line and the last expression can be the return value. An explicit return@<operation> can also be used.

Lambda functions can be used directly or assigned to a variable. When a lambda expression is stored in a variable, you can invoke it as a regular function or using the invoke method. A direct lambda function can be run as a function as well, but is does not offer good readability.

// Regular f(x)
val addOffset = {x : Int -> x + 1}
println(addOffset(2))

// Invoke
println(addOffset.invoke(2))

// Anonymous invocation
println({x : Int -> x + 1}(2))

A lambda can be passed to a function in a lot of ways. If the function requires a lambda as its final parameter, you can take it out of the parentheses. Other than that you use the general syntax of passing arguments.

fun addOffset(base: Int, lambda: (Int) -> Int): Int {
    return lambda.invoke(base)
}

fun addOffset(lambda: (Int) -> Int, base : Int): Int {
    return lambda.invoke(2)
}

// Last argument lambda
addOffset(2) {x : Int -> x + 1}

// General syntax
addOffset ({ x : Int -> x + 1}, 2)

There is another simplification in lambda syntax that I myself is fond of using. If the function has a single argument and its type can be inferred, an autogenerated variable named it will be available for you to use. This is handy on cases wherein you are running out of variable names, or names does not matter much but is not for cases of nested lambdas.

Differences of Java and Kotlin lambdas

Java lambdas can only access final variables. Kotlin on the other hand supports access of non-final variables. This case was briefly touched in another one of my articles. Kotlin supports this feature by wrapping the variables in a reference and the lambda function captures this reference for it to use.

Compatibility with Java Functional Interfaces

Kotlin lambdas are fully compatible with Java functional interfaces. To prove it let us decompile a simple setOnTouchListener call.

button.setOnTouchListener((OnTouchListener)(new OnTouchListener() {
   public final boolean onTouch(View v, MotionEvent e) {
      Intrinsics.checkExpressionValueIsNotNull(v, "v");
      return true;
   }
}));

The compiler is smart enough to know that the function needs an instance of View.OnTouchListener. The compiler interprets a lambda function that represents a functional interface as a instance of an anonymous class implementing that functional interface.

You may think that Kotlin just converts the lambda into an anonymous class just like the old times. Well there is a bit of a catch here. When using anonymous classes explicitly, you are always creating a new instance. But in lambda, if it is not capturing, there will exist a single instance of it that is used on every reuse.

Note: For those who are not familiar, capturing lambdas are lambdas that use variables that are outside their immediate scope. Think of it as a function in a class that uses private fields. You can say it “captures” those variables. Non-capturing on the other hand does not depend on any variable outside their immediate scope. You can think of them as pure functions.

SAM Constructors

Even though the compiler is smart enough to convert your lambda into an anonymous class implementation of functional interfaces, there are still cases wherein you need to explicitly convert. Kotlin supports explicit conversion using the SAM constructors.

SAM constructors allow you to convert a lambda expression to an instance of a function interface. The syntax is pretty straightforward.

FunctionalInterfaceName { lambda_function }

When do you need to do this you say? Let’s take a look at 2 examples.

// Assigning to a variable
val runnable : Runnable = Runnable { print("I am a runnable")}

// Returning a specific type of functional interface
fun createOnClickListener() : View.OnClickListener {
    return View.OnClickListener { v -> print("I am clicked") }
}

Both of this cases requires you to have a specific functional interface type. Lambda cannot be used directly for that.

Java SAM vs. Kotlin Function Types

Kotlin uses function types instead of interfaces. So if you are coding in pure Kotlin, it is important to use function types for lambda types as Kotlin does not support conversion of lambdas to Kotlin interfaces. More on function types soon.

Considerations

Lambdas are not without their overhead. A lambda function by default, under the hood, generates .class and surprisingly, a step towards reaching your DEX limit. There is a good summary here. Thankfully, we can reduce some of these overhead using other features such as inlining. This will be discussed in one of the future articles so watch out for it.

Check out the other articles in the idiomatic kotlin series. The sample source code for each article can be found here in Github.

  1. Extension Functions
  2. Sealed Classes
  3. Infix Functions
  4. Class Delegation
  5. Local functions
  6. Object and Singleton
  7. Sequences
  8. Lambdas and SAM constructors
  9. Lambdas with Receiver and DSL
  10. Elvis operator
  11. Property Delegates and Lazy
  12. Higher-order functions and Function Types
  13. Inline functions
  14. Lambdas and Control Flows
  15. Reified Parameters
  16. Noinline and Crossinline
  17. Variance
  18. Annotations and Reflection
  19. Annotation Processor and Code Generation

original source : https://antonioleiva.com/listeners-several-functions-kotlin/

참고자료) inline reserved keyword 설명    https://antonioleiva.com/lambdas-kotlin/

링크하단 부분에 나옴



One question I get often is how to simplify the interaction with listeners that have several functions on Kotlin. For listeners (or any interfaces) with a single function is simple: it automatically lets you replace it by a lambda. But that’s not the case for listeners with several functions.

So in this article I want to show you different ways to deal with the problem, and you may even learn some new Kotlin tricks on the way!

The problem

When we’re dealing with listeners, let’s say the OnclickListener for views, thanks to optimizations that Kotlin do over Java libraries, we can turn this:

view.setOnClickListener(object : View.OnClickListener { override fun onClick(v: View?) { toast(“View clicked!”) }})

into this:

view.setOnClickListener { toast(“View clicked!”) }

The problem is that when we get used to it, we want it everywhere. But this doesn’t escalate when the interface has several functions.

For instance, if we want to set a listener to a view animation, we end up with this “nice” code:

view.animate() .alpha(0f) .setListener(object : Animator.AnimatorListener { override fun onAnimationStart(animation: Animator?) { toast(“Animation Start”) } override fun onAnimationRepeat(animation: Animator?) { toast(“Animation Repeat”) } override fun onAnimationEnd(animation: Animator?) { toast(“Animation End”) } override fun onAnimationCancel(animation: Animator?) { toast(“Animation Cancel”) } })

You may argue that the Android framework already gives a solution for it: the adapters. For almost any interface that has several methods, they provide an abstract class that implements all methods as empty. In the case above, you could have:

view.animate() .alpha(0f) .setListener(object : AnimatorListenerAdapter() { override fun onAnimationEnd(animation: Animator?) { toast(“Animation End”) } })

Ok, a little better, but this have a couple of issues:

  • The adapters are classes, which means that if we want a class to act as an implementation of this adapter, it cannot extend anything else.
  • We get back to the old school days, where we need an anonymous object and a function to represent something that it’s clearer with a lambda.

What options do we have?

Interfaces in Kotlin: they can contain code

Remember when we talked about interfaces in Kotlin? They can have code, and as such, you can declare adapters that can be implemented instead of extended (you can do the same with Java 8 and default methods in interfaces, in case you’re using it for Android now):

interface MyAnimatorListenerAdapter : Animator.AnimatorListener {
    override fun onAnimationStart(animation: Animator) = Unit
    override fun onAnimationRepeat(animation: Animator) = Unit
    override fun onAnimationCancel(animation: Animator) = Unit
    override fun onAnimationEnd(animation: Animator) = Unit
}

With this, all functions will do nothing by default, and this means that a class can implement this interface and only declare the ones it needs:

class MainActivity : AppCompatActivity(), MyAnimatorListenerAdapter {
    ...
    override fun onAnimationEnd(animation: Animator) {
        toast("Animation End")
    }
}

This solution eliminates one of the problems I explained at the beginning, but it forces us to still declare explicit functions for it. Missing lambdas here?

Besides, though this may save from using inheritance from time to time, for most cases you’ll still be using the anonymous objects, which is exactly the same as using the framework adapters.

But hey! This is an interesting idea: if you need an adapter for listeners with several functions, better use interfaces rather than abstract classes. Composition over inheritance FTW.

Extension functions for common cases

Let’s move to cleaner solutions. It may happen (as in the case above) that most times you just need the same function, and not much interested in the other. For AnimatorListener, the most used one is usually onAnimationEnd. So why not creating an extension function covering just that case?

view.animate()
        .alpha(0f)
        .onAnimationEnd { toast("Animation End") }

That’s nice! The extension function is applied to ViewPropertyAnimator, which is what animate(), alpha, and all other animation functions return.

inline fun ViewPropertyAnimator.onAnimationEnd(crossinline continuation: (Animator) -> Unit) {
    setListener(object : AnimatorListenerAdapter() {
        override fun onAnimationEnd(animation: Animator) {
            continuation(animation)
        }
    })
}

I’ve talked about inline before, but if you still have some doubts, I recommend you to take a look at the official reference.

As you see, the function just receives a lambda that is called when the animation ends. The extension does the nasty work for us: it creates the adapter and calls setListener.

That’s much better! We could create one extension function per function in the listener. But in this particular case, we have the problem that the animator only accepts one listener. So we can only use one at a time.

In any case, for the most repeating cases (like this one), it doesn’t hurt having a function like this. It’s the simpler solution, very easy to read and to understand.

Using named arguments and default values

But one of the reasons why you and I love Kotlin is that it has lots of amazing features to clean up our code! So you may imagine we still have some alternatives. Next one would be to make use of named arguments: this lets us define lambdas and explicitly say what they are being used for, which will highly improve readability.

We can have a function similar to the one above, but covering all the cases:

inline fun ViewPropertyAnimator.setListener(
        crossinline animationStart: (Animator) -> Unit,
        crossinline animationRepeat: (Animator) -> Unit,
        crossinline animationCancel: (Animator) -> Unit,
        crossinline animationEnd: (Animator) -> Unit) {

    setListener(object : AnimatorListenerAdapter() {
        override fun onAnimationStart(animation: Animator) {
            animationStart(animation)
        }

        override fun onAnimationRepeat(animation: Animator) {
            animationRepeat(animation)
        }

        override fun onAnimationCancel(animation: Animator) {
            animationCancel(animation)
        }

        override fun onAnimationEnd(animation: Animator) {
            animationEnd(animation)
        }
    })
}

The function itself is not very nice, but that will usually be the case with extension functions. They’re hiding the dirty parts of the framework, so someone has to do the hard work. Now you can use it like this:

view.animate()
        .alpha(0f)
        .setListener(
                animationStart = { toast("Animation start") },
                animationRepeat = { toast("Animation repeat") },
                animationCancel = { toast("Animation cancel") },
                animationEnd = { toast("Animation end") }
        )

Thanks to the named arguments, it’s clear what’s happening here.

You will need to make sure that nobody uses this without named arguments, otherwise it becomes a little mess:

view.animate()
        .alpha(0f)
        .setListener(
                { toast("Animation start") },
                { toast("Animation repeat") },
                { toast("Animation cancel") },
                { toast("Animation end") }
        )

Anyway, this solution still forces us to implement all functions. But it’s easy to solve: just use default values for the arguments. Empty lambdas will make it:

inline fun ViewPropertyAnimator.setListener(
        crossinline animationStart: (Animator) -> Unit = {},
        crossinline animationRepeat: (Animator) -> Unit = {},
        crossinline animationCancel: (Animator) -> Unit = {},
        crossinline animationEnd: (Animator) -> Unit = {}) {

    ...
}

And now you can do:

view.animate()
        .alpha(0f)
        .setListener(
                animationEnd = { toast("Animation end") }
        )

Not bad, right? A little more complex than the previous option, but much more flexible.

The killer option: DSLs

So far, I’ve been explaining simple solutions, which honestly may cover most cases. But if you want to go crazy, you can even create a small DSL that makes things even more explicit.

The idea, which is taken from how Anko implements some listeners, is to create a helper which implements a set of functions that receive a lambda. This lambda will be called in the corresponding implementation of the interface. I want to show you the result first, and then explain the code that makes it real:

view.animate()
        .alpha(0f)
        .setListener {
            onAnimationStart {
                toast("Animation start")
            }
            onAnimationEnd {
                toast("Animation End")
            }
        }

See? This is using a small DSL to define animation listeners, and we just call the functions that we need. For simple behaviours, those functions can be one-liners:

view.animate()
        .alpha(0f)
        .setListener {
            onAnimationStart { toast("Start") }
            onAnimationEnd { toast("End") }
        }

This has two pros over the previous solution:

  • It’s a little cleaner: you save some characters here, though honestly not worth the effort only because of that
  • It’s more explicit: it forces the developer say which action they’re overriding. In the previous option, it was up to the developer to set the named argument. Here there’s no option but to call the function.

So it’s essentially a less-prone-to-error solution.

Now to the implementation. First, you still need an extension function:

fun ViewPropertyAnimator.setListener(init: AnimListenerHelper.() -> Unit) {
    val listener = AnimListenerHelper()
    listener.init()
    this.setListener(listener)
}

This function just gets a lambda with receiver applied to a new class called AnimListenerHelper. It creates an instance of this class, makes it call the lambda, and sets the instance as the listener, as it’s implementing the corresponding interface. Let’s see how AnimeListenerHelper is implemented:

class AnimListenerHelper : Animator.AnimatorListener {
    ...
}

Then, for each function, it needs:

  • A property that saves the lambda
  • The function for the DSL, that receives the lambda executed when the function of the original interface is called
  • The overriden function from the original interface
private var animationStart: AnimListener? = null

fun onAnimationStart(onAnimationStart: AnimListener) {
    animationStart = onAnimationStart
}

override fun onAnimationStart(animation: Animator) {
    animationStart?.invoke(animation)
}

Here I’m using a type alias for AnimListener:

private typealias AnimListener = (Animator) -> Unit

This would be the complete code:

fun ViewPropertyAnimator.setListener(init: AnimListenerHelper.() -> Unit) {
    val listener = AnimListenerHelper()
    listener.init()
    this.setListener(listener)
}

private typealias AnimListener = (Animator) -> Unit

class AnimListenerHelper : Animator.AnimatorListener {

    private var animationStart: AnimListener? = null

    fun onAnimationStart(onAnimationStart: AnimListener) {
        animationStart = onAnimationStart
    }

    override fun onAnimationStart(animation: Animator) {
        animationStart?.invoke(animation)
    }

    private var animationRepeat: AnimListener? = null

    fun onAnimationRepeat(onAnimationRepeat: AnimListener) {
        animationRepeat = onAnimationRepeat
    }

    override fun onAnimationRepeat(animation: Animator) {
        animationRepeat?.invoke(animation)
    }

    private var animationCancel: AnimListener? = null

    fun onAnimationCancel(onAnimationCancel: AnimListener) {
        animationCancel = onAnimationCancel
    }

    override fun onAnimationCancel(animation: Animator) {
        animationCancel?.invoke(animation)
    }

    private var animationEnd: AnimListener? = null

    fun onAnimationEnd(onAnimationEnd: AnimListener) {
        animationEnd = onAnimationEnd
    }

    override fun onAnimationEnd(animation: Animator) {
        animationEnd?.invoke(animation)
    }
}

The resulting code looks great, but at the cost of doing much more work.

What solution should I use?

As usual, it depends. If you’re not using it very often in your code, I would say that none of them. Be pragmatic in these situations, if you’re going to write a listener once, just use an anonymous object that implements the interface and keep writing code that matters.

If you see that you need it more times, do a refactor with one of these solutions. I would usually go for the simple extension that just uses the function we are interested in that moment. If you need more than one, then evaluate which one of the two latest alternatives works better for you. As usual, it depends on how extensively you’re going to use it.

Hope this lines help you next time you find yourself in a situation like this. If you solve this differently, please let me know in the comments!

Thanks for reading 🙂

alt + enter 자동완성

ctrl + space 자동완성 basic code completion

현재 year 가져오기 Calendar.getInstance().get(Calendar.YEAR)

UI를 위한 변수를 자동생성 해주기 위해 필요    

import kotlinx.android.sythetic.main.activity_main.*    

android toast message

Toast.makeText().show()   

kotlin random integer

Random.nextInt()

android drawable

<selector>

      <item>

            <shape>

                  <solid>

                  <corner>

android ImageView

resource 로 부터 이미지 가져오기 

ImageView.setImageResource()

android ListView

BaseAdapter , getItem, getCount, getItemId, getView

ListView.adapter = BaseAdapter를implement한obj

android view layout 

context객체.getSystemService()

android LayoutInflator 객체 얻는법

layoutInflator객체.inflate(Context.LAYOUT_INFLATER_SERVICE)

android activity 

다른 actvity로 이동

Intent, intent객체.putExtra(), startActivity() 

android Bundle activity Intent

intent에서 bundle data가져오기

intent객체.extras 는 Bundle 객체를 return. bundle객체.getString(”키이름”)

android ListView change delete update adapter

adapter객체.notifyDataSetChanged()

kotlin inner class access property

inner modifier

https://stackoverflow.com/a/45418262/3151712

android image drawable mipmap

한번에 다양한 크기의 같은 이미지 생성 프로그램

final_android_resizer

android GridView

ListView와 제작방법이 거의 동일하다.BaseAdapter , getItem, getCount, getItemId, getView. 단 GridView에 numColumns, columnWidth, horizontalSpacing 속성을 추가로 설정해야 한다.

GridView.adapter = BaseAdapter를implement한obj

android internet permission http

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

android kotlin thread background

AsyncTask<> , doInBackground, onProgressUpdate, onPreExecute, onPostExecute

kotlin try catch

try{

}catch (ex:Exception){

}

android kotlin url connection

Url(url스트링) 하면 url객체를 얻을 수 있다. 

url객체.openConnection()하면 urlconnection객체를 얻을수있고 이를 HttpUrlConnection 객체나 HttpsUrlConnection객체로 타입전환할수 있다. HttpUrlConnection객체.connectTimeout() 을 통해 제한시간 설정가능

HttpUrlConnection.inputStream 을 통해 외부로부터 data를 받을수 있게 된다.

InputStream, InputStreamReader, BufferedReader 를 사용 한줄 한줄 읽어 온다.

android json 

JSONObect(스트링) , getJSONObect() 또는 getJSONArray()를 통해 한단계씩 들어가서 데이터를 가져온다.

android drawable background 

상태에 따른 스타일 바꾸기

<selector>  <item> <shape> <corner> <stroke> <solid> <padding>

<item android:state_pressed= “true”>

android firebase authentication analytics

Udemy kotlin android 강좌 

google firebase 사용방법 121 analytics ,122  authentication 매우 간단하고 이해하기 쉽다.

124 analytics

127 datastore database

130 3:00 addValueEventListener

android notification 

NotificationCompat.builder()

setDefault() setSmallIcon() setContentTitle() setContentText() setNumber()

context.getSystemService(context.NOTIFICATION_SERVICE)

Udemy kotlin android 강좌 132

android notification channel

NotificationChannel()

android image 사용 external storage camera permission

ActivityCompat.checkSelfPermission() 

requestPermissions()

onRequestPermissionsResult()

udemy 136 3:00 

android image file 디바이스에 있는 image file 가져오기

intent   intent.ACTION_PICK   android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI   startActivityForResult()

android image file content provider 사용자가 선택한 화일 가져오기

image

android filebase storage imageview에 있는 이미지를 압축해서 firebase storage에 올리기

FirebaseStorage   FirebaseStorage객체.getRefenceFromUrl()   

udemy 137

image

android google firebase authentication 

FirebaseAuth   createUserWithEmailAndPassword()   addOnCompleteListener()

FirebaseUser 

image

android picasso imageview image

udemy 140 9:00

android cloud messaging firebase

앱을 사용하는 다수의 사용자에게 message 보낼때사용. udemy 144

FirebaseMessaging.getInstance().subscribeToTopic()

manifest에 service추가 , meta-data 추가

Service class 작성  onMessageReceived()   

android kotlin variable element

참고) kotlin에서는 findById()과정없이 바로 element id통해 접근가능하다.

아래와 같이 사용해도 된다.

image

위와 같이 activity 안에 요소를 위한 variable을 만들고 view type을 명시적으로 해준경우 아래와 같이 <Button>을 해줘도 되고 안해도 된다.

image

그러나 아래와 같이 activity 안 어느 함수안에서 variable이 정의된경우 photoGalleryButton처럼 명시해주어야 한다.

image

android kotlin clicklistener listener lambda button

image

android kotlin photo picture intent

image

android photo gallery pick intent

image

android kotlin element id variable

image

kotlin에서는 findById()과정없이 바로 element id통해 접근가능하다.

android kotlin inputStream url http read buffer BufferedReader InputStreamReader

image

참고) BuffredReader에 대하여 https://www.baeldung.com/java-buffered-reader

android kotlin Toolbar ActionBar

아래에서는 toolbar는 activity_main layout에 있는 toolbar 의 id 이다.

image

android kotlin network 

network에 연결되었는지 확인하는 경우

image
image

android kotlin AlertDialog 

image
image

android kotlin bitmap url http 

image

android kotlin progress bar 

image

android kotlin button drawable background

gradientdrawable을 xml이 아닌 코드상에서 만드는 방법

image

android kotlin dp float drawable

gradientdrawable을 xml이 아닌 코드상에서 만들때 코너를 둥글게 만드는 경우 dp 사이즈를 설정해 주는데 이때 필요한 dp 값을 구하는 방법이다.

image

kotlin inner class nested 

https://stackoverflow.com/a/46730214/3151712

android kotlin listener anonymous class lambda sam

https://antonioleiva.com/lambdas-kotlin-android/

android kotlin listener anonymous class lambda sam

https://antonioleiva.com/listeners-several-functions-kotlin/

https://antonioleiva.com/lambdas-kotlin/

android kotlin draw onDraw

https://stackoverflow.com/questions/13640541/view-ondrawcanvas-c-versus-drawcanvas-c-in-android

android kotlin TextUtils isEmpty EditText가 비었는지 확인 축약형

https://stackoverflow.com/a/6290637/3151712

android kotlin bundle 만들기 축약형

https://medium.com/@programmerr47/creating-bundles-nicely-with-kotlin-1526fc173d01

옛날방법 https://stackoverflow.com/a/59957980/3151712

android kotlin invoke operator overload

https://stackoverflow.com/questions/45173677/invoke-operator-operator-overloading-in-kotlin

android studio json to kotlin plugin

json 내용을 보고 그에 맞는 kotlin classes를 자동으로 만들어 준다.

android studio – > preferences -> plugin -> json to kotlin 검색

kotlin reference member class ::

https://stackoverflow.com/a/51813211/3151712

kotlin by keyword delegate delegation

https://stackoverflow.com/a/57637851/3151712

original source : https://youtu.be/Xjdv31k-Kf4

이 동영상은 1시간 분량인데 굉장히 설명이 잘되있으며 단계별 정리가 되어있다.

digitalocean 에 프로젝트 올릴때 사용했다. 위 동영상은 새로 시작하는setting 작업이고 이미 있는 프로젝트의 deploy는 https://www.digitalocean.com/community/tutorials/how-to-set-up-django-with-postgres-nginx-and-gunicorn-on-ubuntu-16-04#create-and-configure-a-new-django-project 를 따라 할수 있다. 이를 기반으로 한 동영상은 https://youtu.be/BrVHwQ-SJUA 이며 이는 apache가 아닌 Gunicorn wsgi를 이용했다. 

image
image
image

위는 ubuntu 처음 시작전 update와 upgrade를 하는 과정이다. 

image

동영상 게시자가 추천하는 구조이다.꼭 따라야 하는 것은 아니다. 

image
pip install -r /path/to/requirements.txt

requirements.txt에 있는 libraries들을 설치하는 방법

git clone, fetch, pull의 차이점 설명

https://stackoverflow.com/questions/3620633/what-is-the-difference-between-pull-and-clone-in-git

image
image

위에서 호스트 주소가 바뀐것을 유심히 볼것

image

mysql_secure_installation는 보안성을 높이는 과정이다. 

https://stackoverflow.com/q/20760908/3151712 참조

image

데이터베이스 연결정보 화일을 외부에 두는 방법이다. (옵셥사항)

image

최초 migrate을 통해 admin tables생성및 django superuser만드는법

image

아이피주소뒤에 붙는 port 주소를 없애기위해서는 apache server가 필요하다.그리고 설정수정을 한다.

image

python-path =  이값은 manage.py가 있는 경로

python-hom =  이값은 virtual env가 있는 경로

image
image

static화일 경로 설정이 필요하다.