Retrofit2_간단한 게시판 예제_스와이프레이아웃_선택아이템 삭제

소정·2023년 3월 17일
0

Android_with_Java

목록 보기
30/33

🔨 제목줄 상위로 가기 버튼

package com.bsj0420.ex87retrofitmarcketapp;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;

public class EditActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_edit);

        getSupportActionBar().setTitle("글 작성");
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        
    }

    @Override
    public boolean onSupportNavigateUp() {
        finish();
        return super.onSupportNavigateUp();
    }
}

실습 예제

0. Retrofit 객체 만드는 것 class로 만들기

package com.bsj0420.ex87retrofitmarcketapp;

import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.converter.scalars.ScalarsConverterFactory;

public class RetrofitHelper {

    public static Retrofit getRetrofitInstance(){

        Retrofit.Builder builder = new Retrofit.Builder();
        builder.baseUrl("http://내 닷홈 주소");
        builder.addConverterFactory(ScalarsConverterFactory.create()); //스칼라를 먼저 써여함
        builder.addConverterFactory(GsonConverterFactory.create());
        Retrofit retrofit = builder.build();
        return retrofit;
    }

}

[1] EditActivity

핵심으로 볼 내용

  1. php에 보낼 때 String 데이터들을 Part박스에 묶어서 보내기***
  2. Retrofit으로 이미지 보내기
  3. php에서 특수문자 처리 기능 : addslashes(슬래시가 필요한 곳에 알아서 넣어짐)

edit.xml

android:ems : 글자크기 정해놓기

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical"
    android:padding="16dp"
    tools:context=".EditActivity">

    <EditText
        android:id="@+id/et_name"
        android:inputType="text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:hint="작성자 이름"
        android:ems="10"/>

    <EditText
        android:id="@+id/et_title"
        android:inputType="text"
        android:hint="title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

    <EditText
        android:id="@+id/et_msg"
        android:inputType="textMultiLine"
        android:layout_weight="1"
        android:gravity="top"
        android:hint="message"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

    <EditText
        android:id="@+id/et_price"
        android:inputType="number"
        android:hint="price"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

    <Button
        android:id="@+id/btn_select"
        android:layout_gravity="right"
        android:text="select img"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

    <ImageView
        android:id="@+id/iv"
        android:background="#DCDCDC"
        android:padding="4dp"
        android:layout_width="match_parent"
        android:layout_height="200dp"/>

    <Button
        android:id="@+id/btn_complete"
        android:text="complete"
        android:backgroundTint="@color/black"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</LinearLayout>

edit.java

String 파일들 한번에 묶어 보내기 위해 Map에 넣어서 보낸다

package com.bsj0420.ex87retrofitmarcketapp;

import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.appcompat.app.AppCompatActivity;
import androidx.loader.content.CursorLoader;

import android.content.Intent;

import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.widget.Toast;

import com.bsj0420.ex87retrofitmarcketapp.databinding.ActivityEditBinding;
import com.bumptech.glide.Glide;

import java.io.File;
import java.util.HashMap;
import java.util.Map;

import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;

public class EditActivity extends AppCompatActivity {

    ActivityEditBinding binding;

    //업로드할 이미지의 파일 경로 변수
    String imgPath = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        binding= ActivityEditBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());

        getSupportActionBar().setTitle("글 작성");
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);

        //이미지 선택
        binding.btnSelect.setOnClickListener(v->clickSelect());
        binding.btnComplete.setOnClickListener(v->clickComplete());

    }

    private void clickComplete() {

        //사용자가 입력한 데이터들을 서버에 전송

        //전송할 데이터들
        //작성자 이름, 타이틀, msg, price, imgPath
        String name = binding.etName.getText().toString();
        String title = binding.etTitle.getText().toString();
        String msg = binding.etMsg.getText().toString();
        String price = binding.etPrice.getText().toString();

        //작업 5단계
        //1
        Retrofit retrofit = RetrofitHelper.getRetrofitInstance();

        //2 요구 명세

        //3.
        RetrofitService retrofitService= retrofit.create(RetrofitService.class);

        //4.
        //Stirng 데이타들
        Map<String,String> dataPart = new HashMap<>();
        dataPart.put("name",name);
        dataPart.put("title",title);
        dataPart.put("msg",msg);
        dataPart.put("price",price);

        //이미지 파일 택배박스
        MultipartBody.Part filePart = null;

        if(imgPath != null) { //사진 업로드 안할 때
            File file = new File(imgPath);
            RequestBody body= RequestBody.create(MediaType.parse("image/*"), file);
            filePart= MultipartBody.Part.createFormData("img", file.getName(), body);
        }

        Call<String> call= retrofitService.postDataToServer(dataPart, filePart);

        //5.
        call.enqueue(new Callback<String>() {
            @Override
            public void onResponse(Call<String> call, Response<String> response) {
                String s= response.body();
                Toast.makeText(EditActivity.this, s, Toast.LENGTH_SHORT).show();
                
                //게시글 업로드 성공 했으니 ..글작성화면 자동 종료
                finish();
            }

            @Override
            public void onFailure(Call<String> call, Throwable t) {
                Toast.makeText(EditActivity.this, "error : " + t.getMessage(), Toast.LENGTH_SHORT).show();
            }
        });

    }

    
    private void clickSelect() {

        Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES); //퍼미션 없이 쓸수 있는 이미지픽
        //결과를 받기위한 스타트 액티비티 => ActivityResultLauncher
        resultLauncher.launch(intent);

    }

    ActivityResultLauncher<Intent> resultLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
        if(result.getResultCode() == RESULT_CANCELED) return; //사진 선택 안하고 왔으면 리턴

        Uri uri = result.getData().getData();
        Glide.with(this).load(uri).into(binding.iv);
        
        //Retrofit을 이용하여 서버에 이미지 보낼때는 파일의 주소가 필요
        imgPath = getFilePathFromUri(uri);
        //new AlertDialog.Builder(this).setMessage(imgPAth).show();
    });

    //Uri -- > 절대경로로 바꿔서 리턴시켜주는 메소드
    String getFilePathFromUri(Uri uri){
        String[] proj= {MediaStore.Images.Media.DATA};
        CursorLoader loader= new CursorLoader(this, uri, proj, null, null, null);
        Cursor cursor= loader.loadInBackground();
        int column_index= cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        cursor.moveToFirst();
        String result= cursor.getString(column_index);
        cursor.close();
        return  result;
    }

    @Override
    public boolean onSupportNavigateUp() {
        finish();
        return super.onSupportNavigateUp();
    }
}

RetrofitService.Interface

  • @FormUrlEncoded 와 @Multipart는 같이 쓸 수 없다
  • 이미지 파일용 Part와 나머지 문자열 데이터들 PartMap(여러 데이타 보내기 위해) 으로 구분하여 전송
package com.bsj0420.ex87retrofitmarcketapp;

import java.util.ArrayList;
import java.util.Map;

import okhttp3.MultipartBody;
import retrofit2.Call;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.GET;
import retrofit2.http.Multipart;
import retrofit2.http.POST;
import retrofit2.http.Part;
import retrofit2.http.PartMap;
import retrofit2.http.Query;

public interface RetrofitService {

    //POST방식으로 보낼 때
    //이미지 파일용 Part와 나머지 문자열 데이터들 PartMap(여러 데이타 보내기 위해) 으로 구분하여 전송
    //Part는 하나만 들어갈 수 있음
    //즉, 택배박스 2개로..
    @Multipart
    @POST("RetrofitMarket/insertDB.php")
    Call<String> postDataToServer(@PartMap Map<String,String> dataPart, @Part MultipartBody.Part filePart);
    //@FormUrlEncoded 와 @Multipart 같이 쓸 수 없음
    //@Body로 보내거나 데이타용 박스 (Part)와 이미지용 박스 각각 만들어서 보내기

insert.php

<?php

    header("Content-Type:text/plain; charset=utf-8");


    //@PartMap으로 전달 된 POST방식의 데이터들
    $name= $_POST['name'];
    $title= $_POST['title'];
    $msg= $_POST['msg'];
    $price= $_POST['price'];

    //@Part로 전달된 이미지 파일
    $file= $_FILES['img'];
    $srcName= $file['name'];     //원본파일명
    $tmpName= $file['tmp_name']; //임시저장소 경로/파일명

    //이미지 파일을 영구적으로 저장하기 위해 임시 저장소에서 이동
    $dstName= "./image/" . date('YmdHis') . $srcName; //같은 폴더 안에 이미지폴더 안에 
    move_uploaded_file($tmpName, $dstName);

    //메세지 중에 특수문자 사용가능성 있음. - 쿼리문에 문제 될 수 있음
    //특수 문자는 sql에서 잘못 동작될 수 있기에
    //앞에 슬래시를 추가해주기

    $msg= addslashes($msg); // 슬래시가 필요한 곳에 알아서 넣어짐
    $title= addslashes($title);

    //데이터가 저장되는 시간
    $now= date('Y-m-d H:i:s');

    //Mysql DB에 데이터 저장 [테이블명 : market]
    $db = mysqli_connect('localhost','mrhisj23','hi23bye6!','mrhisj23');
    mysqli_query($db, "set names utf8");

    //저장할 데이터($name, $title, $msg, $price, $dstName, $now) 삽입 뭐리문
    $sql = "INSERT INTO market(name,title,msg,price,image,date) VALUES('$name','$title','$msg','$price','$dstName','$now')";
    $result=mysqli_query($db,$sql);
    
    if($result) echo "게시글이 업로드 되었습니다.";
    else echo "게시글 업로드에 실패했습니다. 다시 시도해 주세요.";

    mysqli_close($db);

?>



[2] MainActivity

핵심으로 볼 내용

  1. 스와이프리프레시
  • 라이브러리 추가
  • 리사이클러뷰 감싸서 SwipeRefreshLayout 만들기
  • 자바에서 setOnRefreshListener 붙이기
  1. Glide에 이미지 없을 때 속성 추가
  • error(이미지 없을 경우 보여줄 그림)
  1. Adaper.java에서 선택한 값 삭제 코드

main.xml

SwipeRefreshLayout : 리사이클러뷰를 감싸 작성
-> 스와이프를 사용하기 위해선 라이브러리 추가해야됨!

<?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"
    tools:context=".MainActivity">

    <!-- 리프레시용 레이아웃 : 별도 라이브러리 -->
    <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
        android:id="@+id/refresh_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recycler"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
            android:orientation="vertical"/>

    </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>

    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/fab_edit"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:backgroundTint="@color/purple_500"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:src="@drawable/baseline_edit_24"
        app:tint="@color/white"
        android:layout_margin="16dp"/>

</RelativeLayout>

main.java

  • Retrofit으로 데이터 불러오기
  • 스와이프 레이아웃 작동 리스너
package com.bsj0420.ex87retrofitmarcketapp;

import androidx.appcompat.app.AppCompatActivity;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;

import android.content.Intent;
import android.os.Bundle;
import android.widget.Toast;

import com.bsj0420.ex87retrofitmarcketapp.databinding.ActivityMainBinding;

import java.util.ArrayList;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;

public class MainActivity extends AppCompatActivity {

    ActivityMainBinding binding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        binding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());

        binding.fabEdit.setOnClickListener(view -> {
            startActivity(new Intent(this, EditActivity.class));
        });

        //리프레시
        binding.refreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                loadData();
            }
        });
    }

    @Override
    protected void onResume() {
        super.onResume();

        loadData();
    }

    private void loadData() {

        Retrofit retrofit = RetrofitHelper.getRetrofitInstance();

        RetrofitService retrofitService = retrofit.create(RetrofitService.class);

        Call<ArrayList<MarketItem>> call = retrofitService.loadDataFromServer();

        call.enqueue(new Callback<ArrayList<MarketItem>>() {
            @Override
            public void onResponse(Call<ArrayList<MarketItem>> call, Response<ArrayList<MarketItem>> response) {
                ArrayList<MarketItem> items = response.body();

                MarketAdapter adapter = new MarketAdapter(MainActivity.this, items);
                binding.recycler.setAdapter(adapter); //노티파이 할 필요 없어짐 매번 새로 만드니까

                ///////////
                binding.refreshLayout.setRefreshing(false); //로딩 아이콘 제거하는 명령
                // true면 계속 도는 아이콘 보임

            }

            @Override
            public void onFailure(Call<ArrayList<MarketItem>> call, Throwable t) {
                Toast.makeText(MainActivity.this, "error = "+ t.getMessage(), Toast.LENGTH_SHORT).show();
            }
        });

    }
}

RetrofitService.Interface

//서버에서 echo한 json array를 읽어와서 자동으로 ArrayList로 파싱하는 요구 명세
    @GET("RetrofitMarket/loadDB.php")
    Call<ArrayList<MarketItem>> loadDataFromServer();

php

<?php

    header("Content-Type:application/json; charset=utf-8");

    $db = mysqli_connect('localhost','mrhisj23','hi23bye6!','mrhisj23');
    mysqli_query($db, "set names utf8");

    $sql = "SELECT * FROM market";

    $result = mysqli_query($db,$sql); //결과표를 리턴해줌

    //결과표로 부터 총 레코드 수 
    $rowNum = mysqli_num_rows($result);

    //여러줄 읽어야하므로 각 줄($row)을 요소로 가질 빈 인덱스 배열 준비
    $rows = array();

    for($i=0; $i<$rowNum; $i++){
        $row = mysqli_fetch_array($result, MYSQLI_ASSOC);//한줄을 연관배열로

        $rows[$i] = $row; //2차원 배열로 저장됨 [{},{}]
    }

    //2차원 배열 --> json array 문자열로 변환 및 응답
    echo json_encode($rows);

    mysqli_close($db);
    
?>

리사이클러뷰 관련 파일들

recycler_item.xml

maxLines : 최대 줄 수
ellipsize : 제목 넘어가면 ... 표시

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:padding="8dp"
    android:layout_marginLeft="4dp"
    android:layout_marginRight="4dp"
    android:layout_height="120dp">

    <androidx.cardview.widget.CardView
        android:id="@+id/cv"
        android:layout_width="120dp"
        android:layout_height="match_parent"
        app:cardCornerRadius="8dp">

        <ImageView
            android:id="@+id/iv"
            android:scaleType="centerCrop"
            android:src="@drawable/baseline_edit_24"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>

    </androidx.cardview.widget.CardView>

    <TextView
        android:id="@+id/tv_title"
        android:layout_toRightOf="@+id/cv"
        android:textColor="@color/black"
        android:textStyle="bold"
        android:text="제목"
        android:maxLines="1"
        android:ellipsize="end"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="12dp"
        android:layout_marginTop="8dp"/>

    <TextView
        android:id="@+id/tv_msg"
        android:layout_marginTop="4dp"
        android:maxLines="3"
        android:layout_alignLeft="@+id/tv_title"
        android:layout_below="@+id/tv_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

    <TextView
        android:id="@+id/tv_price"
        android:layout_alignParentBottom="true"
        android:layout_alignLeft="@+id/tv_title"
        android:textStyle="bold"
        android:textColor="@color/purple_700"
        android:text="3000"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

    <ToggleButton
        android:id="@+id/tb_fav"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:background="@drawable/bg_fav"
        android:textOff=""
        android:textOn=""
        android:layout_width="24dp"
        android:layout_height="24dp"/>


</RelativeLayout>

MarketItem.java

package com.bsj0420.ex87retrofitmarcketapp;

public class MarketItem {

    String no;
    String name;
    String title;
    String msg;
    String price;
    String image;
    String date;

    public MarketItem() {
    }

    public MarketItem(String no, String name, String title, String msg, String price, String image, String date) {
        this.no = no;
        this.name = name;
        this.title = title;
        this.msg = msg;
        this.price = price;
        this.image = image;
        this.date = date;
    }
}

MarketAdapter.java

  • glide에 이미지 불러올 없을 때 보여주는 사진 등록
  • 바인딩을 활용해 view들 부르는 법 잘보기
package com.bsj0420.ex87retrofitmarcketapp;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import com.bsj0420.ex87retrofitmarcketapp.databinding.RecyclerItemBinding;
import com.bumptech.glide.Glide;

import java.util.ArrayList;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;

public class MarketAdapter extends RecyclerView.Adapter<MarketAdapter.VH> {

    Context context;
    ArrayList<MarketItem> items;

    public MarketAdapter(Context context, ArrayList<MarketItem> items) {
        this.context = context;
        this.items = items;
    }

    @NonNull
    @Override
    public VH onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(context).inflate(R.layout.recycler_item, parent, false);
        return new VH(itemView); //바인딩 함
    }

    @Override
    public void onBindViewHolder(@NonNull VH holder, int position) {
        MarketItem item = items.get(position);

        holder.binding.tvTitle.setText(item.title);
        holder.binding.tvMsg.setText(item.msg);
        holder.binding.tvPrice.setText(item.price + "원");

        String address ="";
        if (item.image !=null) address = "http://mrhisj23.dothome.co.kr/RetrofitMarket/" + item.image;
        Glide.with(context).load(address).error(R.drawable.baseline_hide_image_24).into(holder.binding.iv); //이미지 안나옴 - DB에 사진 이름만 들어있음

        //Glide는 이미지 "" 이면 오류 안나고 이미지 칸 비어있음 따라서 이미지가 없을 떄 보여줄 이미지 하나 넣어두기 error(이미지 없을 경우 보여줄 그림)

    }

    @Override
    public int getItemCount() {
        return items.size();
    }

    class VH extends RecyclerView.ViewHolder {

        RecyclerItemBinding binding;

        public VH(@NonNull View itemView) {
            super(itemView);
            binding = RecyclerItemBinding.bind(itemView); // itemView = RelativeLayout
            
        }
    }

}

선택한 아이템 삭제

  • 아답터 ViewHolder에서 현재 클릭한 아이템을 얻어와서 삭제 기능 붙이기
  • 선택한 리사이클러뷰 아이템 삭제하기 코드 잘 보기
package com.bsj0420.ex87retrofitmarcketapp;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import com.bsj0420.ex87retrofitmarcketapp.databinding.RecyclerItemBinding;
import com.bumptech.glide.Glide;

import java.util.ArrayList;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;

public class MarketAdapter extends RecyclerView.Adapter<MarketAdapter.VH> {

    Context context;
    ArrayList<MarketItem> items;

    public MarketAdapter(Context context, ArrayList<MarketItem> items) {
        this.context = context;
        this.items = items;
    }

    @NonNull
    @Override
    public VH onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(context).inflate(R.layout.recycler_item, parent, false);
        return new VH(itemView); //바인딩 함
    }

    @Override
    public void onBindViewHolder(@NonNull VH holder, int position) {
        MarketItem item = items.get(position);

        holder.binding.tvTitle.setText(item.title);
        holder.binding.tvMsg.setText(item.msg);
        holder.binding.tvPrice.setText(item.price + "원");

        String address ="";
        if (item.image !=null) address = "http://mrhisj23.dothome.co.kr/RetrofitMarket/" + item.image;
        Glide.with(context).load(address).error(R.drawable.baseline_hide_image_24).into(holder.binding.iv); //이미지 안나옴 - DB에 사진 이름만 들어있음

        //Glide는 이미지 "" 이면 오류 안나고 이미지 칸 비어있음 따라서 이미지가 없을 떄 보여줄 이미지 하나 넣어두기 error(이미지 없을 경우 보여줄 그림)

    }

    @Override
    public int getItemCount() {
        return items.size();
    }

    class VH extends RecyclerView.ViewHolder {

        RecyclerItemBinding binding;

        public VH(@NonNull View itemView) {
            super(itemView);
            binding = RecyclerItemBinding.bind(itemView); // itemView = RelativeLayout
            
            //삭제
            //binding.getRoot(); 아이템뷰 이렇게 부르거나 그냥 itemView
            itemView.setOnLongClickListener(view -> {

                //현재 클릭한 아이템 얻어오기
                MarketItem item = items.get(getLayoutPosition()); //선택한 녀석의 아이템

                //Toast.makeText(context, item.no+"", Toast.LENGTH_SHORT).show();

                //레트로핏을 이용해서 DB에서 해당 아이템을 삭제 요청
                Retrofit retrofit = RetrofitHelper.getRetrofitInstance();
                RetrofitService retrofitService = retrofit.create(RetrofitService.class);
                Call<String> call =retrofitService.deleteItem(item.no);

                call.enqueue(new Callback<String>() {
                    @Override
                    public void onResponse(Call<String> call, Response<String> response) {
                        String s = response.body();

                        Toast.makeText(context, s, Toast.LENGTH_SHORT).show();

                        items.remove(item);
                        notifyDataSetChanged(); //아답터한테 데이터 변경됐다고 말하기
                    }

                    @Override
                    public void onFailure(Call<String> call, Throwable t) {
                        Toast.makeText(context, "삭제 실패 : "+ t.getMessage(), Toast.LENGTH_SHORT).show();
                    }
                });
                
                return true; //롱클릭 끝나고 같이 다시 호출 안되게 하려고 
            });
        }
    }

}

RetrofitService.Interface

//서버  db에서 특정 아이템 삭제하도록 요청하는 명세
    //안드로이드는 db 직접 못 건드림
    @GET("RetrofitMarket/deleteItem.php")
    Call<String> deleteItem(@Query("no") String no);

php 삭제

<?php

    header("Content-Type:text/plain; charset=utf-8");

    //delete 할 아이템의 no 정보
    $no = $_GET['no'];

    $db = mysqli_connect('localhost','mrhisj23','hi23bye6!','mrhisj23');
    mysqli_query($db, "set names utf8");


    $sql="SELECT image FROM market WHERE no=$no";
    $result = mysqli_query($db, $sql);

    $image="";
    if($result){
        $row=mysqli_fetch_array($result, MYSQLI_ASSOC); //한줄로 가져오는 게 좋다
        $image= $row['image']; //경로 찾아오기
    }

    $sql="DELETE FROM market WHERE no=$no";
    $result= mysqli_query($db, $sql);

    if($result){
         echo "아이템이 삭제되었습니다.";

         //저장되어 있는 파일 삭제         
         unlink($image);
    }
    else echo "삭제중 오류발생";

    mysqli_close($db);

?>
profile
보조기억장치

0개의 댓글