마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

new View.OnClickListener()가 작동하지 않습니다.

0 추천
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;

import androidx.appcompat.app.AppCompatActivity;

import com.example.myapplication.R;
import com.google.android.material.textfield.TextInputEditText;
import com.spmemo.db.NoteDatabase;
import com.spmemo.db.model.Note;

import java.lang.ref.WeakReference;

public class AddNoteActivity extends AppCompatActivity {

    private TextInputEditText et_title, et_content;
    private NoteDatabase noteDatabase;
    private Note note;
    private boolean update;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_add_note);
        et_title = findViewById(R.id.et_title);
        et_content = findViewById(R.id.et_content);
        noteDatabase = NoteDatabase.getInstance(AddNoteActivity.this);
        Button button = findViewById(R.id.but_save);
        if ((note = (Note) getIntent().getSerializableExtra("note")) != null) {
            getSupportActionBar().setTitle("Update Note");
            update = true;
            button.setText("Update");
            et_title.setText(note.getTitle());
            et_content.setText(note.getContent());
        }

        // 문제있는 부분
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (update) {
                    note.setContent(et_content.getText().toString());
                    note.setTitle(et_title.getText().toString());
                    noteDatabase.getNoteDao().updateNote(note);
                    // resultCode 보내는 src
                    setResult(note, 2);
                } else {
                    note = new Note(et_content.getText().toString(), et_title.getText().toString());
                    new InsertTask(AddNoteActivity.this, note).execute();
                }
            }
        });
    }

    // resultCode 반환 메서드
    private void setResult(Note note, int flag) {
        setResult(flag, new Intent().putExtra("note", note));
        finish();
    }

    private static class InsertTask extends AsyncTask<Void, Void, Boolean> {

        private WeakReference<AddNoteActivity> activityReference;
        private Note note;

        // only retain a weak reference to the activity
        InsertTask(AddNoteActivity context, Note note) {
            activityReference = new WeakReference<>(context);
            this.note = note;
        }

        // doInBackground methods runs on a worker thread
        @Override
        protected Boolean doInBackground(Void... objs) {
            // retrieve auto incremented note id
            long j = activityReference.get().noteDatabase.getNoteDao().insertNote(note);
            note.setNote_id(j);
            Log.e("ID ", "doInBackground: " + j);
            return true;
        }

        // onPostExecute runs on main thread
        @Override
        protected void onPostExecute(Boolean bool) {
            if (bool) {
                activityReference.get().setResult(note, 1);
                activityReference.get().finish();
            }
        }
    }


}

 

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
    android:layout_margin="4dp"
    tools:context="com.spmemo.AddNoteActivity"
    android:orientation="vertical">

    <com.google.android.material.textfield.TextInputLayout
        android:id="@+id/txtInput"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <com.google.android.material.textfield.TextInputEditText
            android:inputType="text"
            android:id="@+id/et_title"
            android:hint="Title"
            android:singleLine="true"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    </com.google.android.material.textfield.TextInputLayout>

    <LinearLayout
        android:layout_below="@+id/txtInput"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <com.google.android.material.textfield.TextInputLayout
            android:id="@+id/txtInput2"
            android:layout_width="match_parent"
            android:layout_weight="1"
            android:layout_height="0dp">
            <com.google.android.material.textfield.TextInputEditText
                android:id="@+id/et_content"
                android:hint="Content"
                android:gravity="top"
                android:singleLine="false"
                android:inputType="textMultiLine|textNoSuggestions"
                android:layout_width="match_parent"
                android:layout_height="match_parent" />
        </com.google.android.material.textfield.TextInputLayout>

        <Button
            android:background="@drawable/button_bg"
            android:id="@+id/but_save"
            android:text="Save"
            android:layout_gravity="center"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

    </LinearLayout>

</RelativeLayout>

 

 

 

 

자바 파일과 xml 파일입니다. 

 

이것저것 만져보아도 OnClickListener()가 회색상태입니다.. 혹시 xml 문제일까요?

류진 (120 포인트) 님이 2022년 2월 14일 질문

1개의 답변

0 추천

문제가 있는 것이 아니라, 안들로이드 스튜디오가 해당 코드에 대한 추천사항이 있다는 표시입니다. View.OnClickListener를 마우스 오른쪽 클릭해보시면 아마 "convert to lamdba" 가 보이실 겁니다. View.OnClickListener는  

public void onClick(View view)

메소드 하나만 가진 인터페이스이므로, 이렇게 메소드를 하나만 가진 인터페이스는 Lambda expression(람다 표현식)을 사용할 수 있습니다. Java8 부터 지원되는 기능으로 View.OnClickListener는 아래처럼 onClick메소드 선언부만 상요해서 처리할 수 있습니다.

button.setOnClickListener(new View.OnClickLsitener() {
    @Override
     public void onClick(View view) {
          ...
     }
});


 

이 코드를 람다식을 써서 간략하게 표현할 수 있습니다.

button.setOnClickListener(v -> {
    // 멀티라인의 코드
});


button.setOnClickListener(v -> /*싱글라인의 코드*/ );

publc void onClick(View view)의 파라미터가 View이므로
View.OnClickListener는

(View v) -> { }

로 간략하게 표기가 가능하며,  View타입도 생략이 가능하므로 

v -> {}

로 사용할 수 있습니다. 람다를 하나의 타입으로 보시면 됩니다. View.OnClickListener의 onClick은 View 타입을 받아서 void를 리턴하는 함수타입으로 볼 수 있습니다.

리스너를 설정하는 기존코드는  boiler plate에 해당하는 코드이므로 굳이 사용할 필요가 없습니다. 개인적으로도 람다를 사용하는 걸 추천합니다. 조금만 써보면  어렵지 않고 금방 눈에 들어옵니다. boiler plate코드에 신경을 쓰지 않아도 되므로, 가독성이 올라갑니다.

spark (227,470 포인트) 님이 2022년 2월 14일 답변
...