안드로이드에서 원격지의 json 파일 호출후
Recyclerview 를 이용하여 화면에 출력하려고 하는데
오류가 계속 발생합니다.
처음에는 onCreateViewHolder 메소드를 호출 안하더라구요.
아래 링크 참조하여 해결했습니다.
그런데 또 다른 문제가 발생합니다.
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 |