안드로이드에서 원격지의 json 파일 호출후
Recyclerview 를 이용하여 화면에 출력하려고 하는데
오류가 계속 발생합니다.
처음에는 onCreateViewHolder 메소드를 호출 안하더라구요.
아래 링크 참조하여 해결했습니다.
[java] Recyclerview가 onCreateViewHolder를 호출하지 않습니다 - 리뷰나라
내는 RecyclerView호출하지 않습니다 onCreateViewHolder, onBindViewHolder도 MenuViewHolder에 따라서 아무것도 나타납니다, 생성자를 RecyclerView. 디버깅을 위해 로그를 넣고 로그가 표시되지 않습니다. 무엇이
daplus.net
그런데 또 다른 문제가 발생합니다.
E/RecyclerView: No adapter attached; skipping layout .. .. .. D/AndroidRuntime: Shutting down VM E/AndroidRuntime: FATAL EXCEPTION: main Process: com.example.mycoupang, PID: 30655 android.view.InflateException: Binary XML file line #16 in com.example.mycoupang:layout/card_layout_main: RecyclerView has no LayoutManager androidx.recyclerview.widget.RecyclerView{7745bc3 VFED..... ......I. 0,0-0,0 #7f070023 app:id/cardSiteCardView}, adapter:null, layout:null, context:com.example.mycoupang.MainActivity@152cecb Caused by: java.lang.IllegalStateException: RecyclerView has no LayoutManager androidx.recyclerview.widget.RecyclerView{7745bc3 VFED..... ......I. 0,0-0,0 #7f070023 app:id/cardSiteCardView}, adapter:null, layout:null, context:com.example.mycoupang.MainActivity@152cecb at androidx.recyclerview.widget.RecyclerView.generateLayoutParams(RecyclerView.java:4304)
이문제는 어댑터 또는 xml 에 문제가 있는것 같지만
아직도 해결을 못하고 있습니다.
MainActivity.java
package com.example.mycoupang; import androidx.appcompat.app.AppCompatActivity; import androidx.recyclerview.widget.DefaultItemAnimator; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import android.content.ContentValues; import android.content.Intent; import android.content.pm.ActivityInfo; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; import android.view.View; import android.widget.ImageView; import org.json.JSONArray; import org.json.JSONObject; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; public class MainActivity extends AppCompatActivity { RecyclerView lecyclerView; ArrayList<CardForSite> list = new ArrayList<>(); Handler handler; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //세로모드 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); setContentView(R.layout.activity_main); getSupportActionBar().setTitle("좋아"); /* final ImageView img1 = findViewById(R.id.imageView2); img1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(); intent.setAction(Intent.ACTION_VIEW); intent.addCategory(Intent.CATEGORY_BROWSABLE); intent.setData(Uri.parse("http://zzz.com/more/?p=aHR0cHM6Ly9jb3VwYS5uZy9iNTFqQTk=")); startActivity(intent); } }); */ /** * https://riucc.tistory.com/375 */ lecyclerView = (RecyclerView) findViewById(R.id.recyclerView); String url = "http://zzzz.com/android.php"; NetworkTask networkTask = new NetworkTask(url, null); networkTask.execute(); // 뷰를 띄우기 위한 구문(이렇게 안뜨면 아래로 방법으로) /* lecyclerView.setAdapter(new RecycleAdapter(list, R.layout.card_layout_main)); lecyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext())); lecyclerView.setItemAnimator(new DefaultItemAnimator()); */ // 위에껄로 하다보니 데이터를 많이 가져와 띄워주니 안뜨는 거를 볼 수 있었다 // 핸들러를 통해 1초 이후에 뜨게 하니 정상적으로 잘 뜬다!!! handler = new Handler(); handler.postDelayed(new Runnable() { @Override public void run() { lecyclerView.setAdapter(new RecycleAdapter(list, R.layout.card_layout_main)); System.out.println(">>>> aaa"); lecyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext())); System.out.println(">>>> bb"); lecyclerView.setItemAnimator(new DefaultItemAnimator()); System.out.println(">>>> cc"); } }, 1000); // 1000 = 1초 후 도출 } public class NetworkTask extends AsyncTask<Void, Void, String> { private String url; private ContentValues values; public NetworkTask(String url, ContentValues values) { this.url = url; this.values = values; } @Override protected String doInBackground(Void... params) { String result; // 요청 결과를 저장할 변수. RequestHttpURLConnection requestHttpURLConnection = new RequestHttpURLConnection(); result = requestHttpURLConnection.request(url, values); // 해당 URL로 부터 결과물을 얻어온다. return result; } @Override protected void onPostExecute(String s) { super.onPostExecute(s); //textView.setText(s); } } public class RequestHttpURLConnection { public String request(String _url, ContentValues _params) { // HttpURLConnection 참조 변수. HttpURLConnection urlConn = null; // URL 뒤에 붙여서 보낼 파라미터. StringBuffer sbParams = new StringBuffer(); /** * 1. StringBuffer에 파라미터 연결 * */ // 보낼 데이터가 없으면 파라미터를 비운다. if (_params == null) // sbParams.append(""); // sbParams.append("miseID=" + miseID); //sbParams.append("&misePW=" + misePW); //sbParams.append("miseID=test001&misePW=test001&miseNAME=테스트001"); //sbParams.append("memberID=test123&password=test123&name=꼬북이&email=test123@naver.com"); // 보낼 데이터가 있으면 파라미터를 채운다. /** * 2. HttpURLConnection을 통해 web의 데이터를 가져온다. * */ try { URL url = new URL(_url); urlConn = (HttpURLConnection) url.openConnection(); // [2-1]. urlConn 설정. urlConn.setRequestMethod("POST"); // URL 요청에 대한 메소드 설정 : POST. urlConn.setRequestProperty("Accept-Charset", "UTF-8"); // Accept-Charset 설정. urlConn.setRequestProperty("Context_Type", "application/x-www-form-urlencoded;cahrset=UTF-8"); // [2-2]. parameter 전달 및 데이터 읽어오기. String strParams = sbParams.toString(); //sbParams에 정리한 파라미터들을 스트링으로 저장. 예)id=id1&pw=123; OutputStream os = urlConn.getOutputStream(); os.write(strParams.getBytes("UTF-8")); // 출력 스트림에 출력. os.flush(); // 출력 스트림을 플러시(비운다)하고 버퍼링 된 모든 출력 바이트를 강제 실행. os.close(); // 출력 스트림을 닫고 모든 시스템 자원을 해제. // [2-3]. 연결 요청 확인. // 실패 시 null을 리턴하고 메서드를 종료. if (urlConn.getResponseCode() != HttpURLConnection.HTTP_OK) return null; // [2-4]. 읽어온 결과물 리턴. // 요청한 URL의 출력물을 BufferedReader로 받는다. BufferedReader reader = new BufferedReader(new InputStreamReader(urlConn.getInputStream(), "UTF-8")); // 출력물의 라인과 그 합에 대한 변수. String line; String page = ""; // 라인을 받아와 합친다. // 버퍼의 웹문서 소스를 줄 단위로 읽어(line), page에 저장함 while ((line = reader.readLine()) != null) { page += line; } try { // JSP에서 보낸 JSON 받아오자 JSONObject = siteDataMain JSONObject json = new JSONObject(page); JSONArray jArr = json.getJSONArray("naya"); // JSON이 가진 크기만큼 데이터를 받아옴 for (int i = 0; i < jArr.length(); i++) { json = jArr.getJSONObject(i); System.out.println(i + "번째 데이터 : " + json.getString("id")); System.out.println(i + "번째 데이터 : " + json.getString("name")); System.out.println(i + "번째 데이터 : " + json.getString("address")); System.out.println(i + "번째 데이터 : " + json.getString("img")); System.out.println("\n"); list.add(new CardForSite(json.getString("id"), json.getString("name"), json.getString("address"), json.getString("img"))); } /* 여기까지 서버가 보낸 데이터를 받아 왔다. 밑에는 확인을 위한 수행 */ //String data = "받은 데이터 : " + getJsonData[0] + " " + getJsonData[1]; //setTextView(data); } catch (Exception e) { e.printStackTrace(); } } catch (MalformedURLException e) { // for URL. e.printStackTrace(); } catch (IOException e) { // for openConnection(). e.printStackTrace(); } finally { if (urlConn != null) urlConn.disconnect(); } return null; } } }
activity_main.xml
<?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" tools:context=".MainActivity"> <!-- <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingLeft="10dp" android:paddingRight="10dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"> <ImageView android:id="@+id/imageView2" android:layout_width="380dp" android:layout_height="80dp" android:scaleType="fitCenter" app:srcCompat="@drawable/main_coupang" /> </LinearLayout> --> <androidx.recyclerview.widget.RecyclerView android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/recyclerView" /> </LinearLayout>
card_layout_main.xml
<?xml version="1.0" encoding="utf-8"?> <androidx.recyclerview.widget.RecyclerView xmlns:card_view="http://schemas.android.com/apk/res-auto" xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="450dp" card_view:cardCornerRadius="5dp" card_view:cardElevation="10dp" android:id="@+id/cardSiteCardView" android:layout_margin="5dp" > <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <ImageView android:layout_width="match_parent" android:layout_height="170dp" android:id="@+id/cardSiteImage" android:scaleType="centerCrop"/> <TextView android:textStyle="bold" android:id="@+id/cardSiteTitle" android:gravity="center_vertical" android:layout_width="match_parent" android:singleLine="true" android:ellipsize="end" android:layout_height="30dp" /> <TextView android:ellipsize="end" android:id="@+id/cardSiteText" android:gravity="center_vertical" android:layout_width="match_parent" android:layout_height="50dp" /> </LinearLayout> </androidx.recyclerview.widget.RecyclerView>
RecycleAdaper.java
package com.example.mycoupang; import android.content.Context; import android.content.Intent; import android.net.Uri; import androidx.cardview.widget.CardView; import androidx.recyclerview.widget.RecyclerView; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import com.daimajia.androidanimations.library.Techniques; import com.daimajia.androidanimations.library.YoYo; import com.squareup.picasso.Picasso; import java.util.List; /** * Created by riu on 2018-03-31. */ public class RecycleAdapter extends RecyclerView.Adapter<RecycleAdapter.ViewHolder> { private List<CardForSite> dataList; private int itemLayout; /** * 생성자 * * @param items * @param itemLayout */ public RecycleAdapter(List<CardForSite> items, int itemLayout) { System.out.println(">>>>> 000:"); this.dataList = items; this.itemLayout = itemLayout; } /** * 레이아웃을 만들어서 Holer에 저장 * * @param viewGroup * @param viewType * @return */ @Override public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { System.out.println(">>>>> 111:"); View view = LayoutInflater.from(viewGroup.getContext()).inflate(itemLayout, viewGroup, false); return new ViewHolder(view); } /** * listView getView 를 대체 * <p> * 넘겨 받은 데이터를 화면에 출력하는 역할 * * @param viewHolder * @param position */ @Override public void onBindViewHolder(ViewHolder viewHolder, int position) { final CardForSite item = dataList.get(position); System.out.println(">>>>> 222:" + item.getSiteLink()); viewHolder.cardSiteTitle.setText(item.getSiteTitle()); viewHolder.cardSiteText.setText(item.getSitetext()); viewHolder.cardSiteImage.setTag(item); // 애니메이션 FadeIn 카드뷰에 적용하기 위한 YoYo.with(Techniques.FadeIn).playOn(viewHolder.cardSiteCardView); // 피카소를 이용하여 url 이미지 쉽게 하기 위한 // gradle에 넣어야할 것도 있음 String imageUrl = item.getSiteImage(); Context context = viewHolder.cardSiteImage.getContext(); Picasso.get() .load(imageUrl) .into(viewHolder.cardSiteImage); // 아이템뷰(하나의 카드뷰) 링크 클릭 리스너 viewHolder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent it = new Intent(Intent.ACTION_VIEW, Uri.parse(item.getSiteLink())); view.getContext().startActivity(it); } }); } @Override public int getItemCount() { System.out.println(">>>> getItemCount:"+dataList.size()); return dataList.size(); } /** * 뷰 재활용을 위한 viewHolder */ public static class ViewHolder extends RecyclerView.ViewHolder { public TextView cardSiteTitle; public TextView cardSiteText; public ImageView cardSiteImage; public CardView cardSiteCardView; public ViewHolder(View itemView) { super(itemView); // 카드뷰 애니메이션 처리를 위한 cardSiteCardView = (CardView) itemView.findViewById(R.id.cardSiteCardView); cardSiteTitle = (TextView) itemView.findViewById(R.id.cardSiteTitle); cardSiteText = (TextView) itemView.findViewById(R.id.cardSiteText); cardSiteImage = (ImageView) itemView.findViewById(R.id.cardSiteImage); } } }
CardForSite.java
package com.example.mycoupang; public class CardForSite { private String siteTitle; private String siteLink; private String siteImage; private String sitetext; public CardForSite(String siteTitle, String siteLink, String sitetext, String siteImage) { this.siteTitle = siteTitle; this.siteLink = siteLink; this.siteImage = siteImage; this.sitetext = sitetext; } public String getSiteTitle() { return siteTitle; } public void setSiteTitle(String siteTitle) { this.siteTitle = siteTitle; } public String getSiteLink() { return siteLink; } public void setSiteLink(String siteLink) { this.siteLink = siteLink; } public String getSiteImage() { return siteImage; } public void setSiteImage(String siteImage) { this.siteImage = siteImage; } public String getSitetext() { return sitetext; } public void setSitetext(String sitetext) { this.sitetext = sitetext; } }
'프로그래밍 > Android' 카테고리의 다른 글
안드로이드 TCP Socket + Webview bridge 샘플 (0) | 2023.02.27 |
---|---|
android socket (소켓통신) 샘플 (0) | 2023.02.20 |
[안드로이드] 웹뷰 + 카카오톡 적용 (0) | 2022.02.04 |
[android] net::ERR_UNKNOWN_URL_SCHEME (0) | 2022.02.04 |
안드로이드 원격 json 읽어 화면에 출력하기 (이미지 포함) (0) | 2021.10.22 |