Я разрабатываю приложение, которое читает из базы данных mySQL, используя объекты PHP и JSON. Затем я хочу, чтобы данные отображались в режиме просмотра / просмотра карт. Я следовал этому учебному пособию онлайн (https://www.simplifiedcoding.net/retrieve-data-mysql-database-android/), и он отлично работает на эмуляторе, но не на моем физическом устройстве (Samsung Galaxy A7 2017).
В журнале событий, когда я запускаю на обоих эмуляторахи устройство получило сообщение об ошибке;
E/RecyclerView: No adapter attached; skipping layout
, но на эмуляторе это все еще работает нормально *
Я следовал за этим вопросом о стеке и не работал; Приложение Android работаетна эмуляторе, но не на реальном устройстве
Где он попросил изменить java android:supportsRtl="true"
на "false" в манифесте.
business_list.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="177dp"
android:paddingTop="10dp"
android:paddingBottom="10dp">
<ImageView
android:id="@+id/ivLogo"
android:layout_width="108dp"
android:layout_height="77dp"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_marginStart="5dp"
android:layout_marginRight="5dp"
android:layout_marginLeft="5dp"
android:layout_marginTop="5dp"
android:layout_marginEnd="1dp"
android:padding="4dp" />
<TextView
android:id="@+id/tvBusName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_marginStart="5dp"
android:layout_marginRight="5dp"
android:layout_marginLeft="5dp"
android:layout_marginTop="5dp"
android:layout_marginEnd="1dp"
android:layout_toRightOf="@id/ivLogo"
android:fontFamily="@font/roboto_slab"
android:text="The Bookshelf"
android:textAppearance="@style/TextAppearance.AppCompat.Display1"
android:textColor="#000000"
android:textSize="24sp" />
<TextView
android:id="@+id/tvAddress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/tvBusName"
android:layout_marginStart="5dp"
android:layout_marginRight="5dp"
android:layout_marginLeft="5dp"
android:layout_marginTop="5dp"
android:layout_marginEnd="1dp"
android:layout_toRightOf="@id/ivLogo"
android:fontFamily="@font/roboto_light_italic"
android:text="78 S Mall, Centre, Cork"
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
<TextView
android:id="@+id/tvBusDesc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/tvAddress"
android:layout_alignParentEnd="true"
android:layout_marginStart="5dp"
android:layout_marginRight="5dp"
android:layout_marginLeft="5dp"
android:layout_marginTop="5dp"
android:layout_marginEnd="1dp"
android:layout_toEndOf="@+id/ivLogo"
android:layout_toRightOf="@id/ivLogo"
android:fontFamily="@font/roboto_light"
android:text="The Bookshelf Coffee House is a comfortable and relaxed experience where you can come and enjoy some home baking and great coffee with friends."
android:textAppearance="@style/TextAppearance.AppCompat.Small" />
</RelativeLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>
activity_main.xml
<?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="wrap_content"
tools:context=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="vertical" />
</RelativeLayout>
Бизнес-класс Business.java
package com.example.loyaltybusiness;
public class Business {
private int merchantId;
private String businessName;
private String address;
private String busDesc;
private String logo;
public Business(int merchantId, String businessName, String address, String busDesc, String logo) {
this.setMerchantId(merchantId);
this.setBusinessName(businessName);
this.setAddress(address);
this.setBusDesc(busDesc);
this.setLogo(logo);
}
// Getters and Setters for the fields we want the customer to see
public int getMerchantId() {
return merchantId;
}
public void setMerchantId(int merchantId) {
this.merchantId = merchantId;
}
public String getBusinessName() {
return businessName;
}
public void setBusinessName(String businessName) {
this.businessName = businessName;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getBusDesc() {
return busDesc;
}
public void setBusDesc(String busDesc) {
this.busDesc = busDesc;
}
public String getLogo() {
return logo;
}
public void setLogo(String logo) {
this.logo = logo;
}
}
BusinessAdapter #
package com.example.loyaltybusiness;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;
import com.bumptech.glide.Glide;
import java.util.ArrayList;
import java.util.List;
public class BusinessAdapter extends RecyclerView.Adapter<BusinessAdapter.BusinessViewHolder> {
private Context mCtx;
private List<Business> businessList;
//public BusinessAdapter(Context mCtx, List<Business> businessList) {
// this.mCtx = mCtx;
// this.businessList = businessList;
//}
public BusinessAdapter(Context mContext) {
this.mCtx = mContext;
}
public void addData(List<Business> businessList) {
this.businessList = businessList;
notifyDataSetChanged();
}
@Override
public BusinessViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(mCtx);
View view = inflater.inflate(R.layout.business_list, parent, false);
return new BusinessViewHolder(view);
}
@Override
public void onBindViewHolder(BusinessViewHolder holder, int position) {
Business business = businessList.get(position);
//loading the image
Glide.with(mCtx)
.load(business.getLogo())
.into(holder.ivLogo);
holder.tvBusName.setText(business.getBusinessName());
holder.tvAddress.setText(business.getAddress());
holder.tvBusDesc.setText(String.valueOf(business.getBusDesc()));
}
@Override
public int getItemCount() {
return businessList.size();
}
class BusinessViewHolder extends RecyclerView.ViewHolder {
TextView tvBusName, tvAddress, tvBusDesc;
ImageView ivLogo;
public BusinessViewHolder(View itemView) {
super(itemView);
tvBusName = itemView.findViewById(R.id.tvBusName);
tvAddress = itemView.findViewById(R.id.tvAddress);
tvBusDesc = itemView.findViewById(R.id.tvBusDesc);
ivLogo = itemView.findViewById(R.id.ivLogo);
}
}
}
MainActivity.java
package com.example.loyaltybusiness;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.text.format.Formatter;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
//this is the JSON Data URL
//make sure you are using the correct ip else it will not work
//WifiManager wm = (WifiManager) getApplicationContext().getSystemService(WIFI_SERVICE);
//String ip = Formatter.formatIpAddress(wm.getConnectionInfo().getIpAddress());
//private final String URL_BUSINESS = "http://" + ip + "/business.php";
private static final String URL_BUSINESS = "http://myipaddress/business.php";
//a list to store all the products
List<Business> businessList;
//the recyclerview
RecyclerView recyclerView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//getting the recyclerview from xml
recyclerView = findViewById(R.id.recyclerView);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
//initializing the productlist
businessList = new ArrayList<>();
//this method will fetch and parse json
//to display it in recyclerview
loadBusiness();
}
private void loadBusiness() {
/*
* Creating a String Request
* The request type is GET defined by first parameter
* The URL is defined in the second parameter
* Then we have a Response Listener and a Error Listener
* In response listener we will get the JSON response as a String
* */
StringRequest stringRequest = new StringRequest(Request.Method.GET, URL_BUSINESS,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
try {
//converting the string to json array object
JSONArray array = new JSONArray(response);
//traversing through all the object
for (int i = 0; i < array.length(); i++) {
//getting product object from json array
JSONObject business = array.getJSONObject(i);
//adding the product to product list
businessList.add(new Business(
business.getInt("merchantId"),
business.getString("businessName"),
business.getString("address"),
business.getString("busDesc"),
business.getString("logo")
));
}
//creating adapter object and setting it to recyclerview
BusinessAdapter adapter = new BusinessAdapter(MainActivity.this);
adapter.addData(businessList);
recyclerView.setAdapter(adapter);
} catch (JSONException e) {
e.printStackTrace();
}
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
}
});
//adding our stringrequest to queue
Volley.newRequestQueue(this).add(stringRequest);
}
}
манифест
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.loyaltybusiness">
<!-- the internet permission -->
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<meta-data
android:name="preloaded_fonts"
android:resource="@array/preloaded_fonts" />
</application>
</manifest>
файлы gradle уровня приложения
apply plugin: 'com.android.application'
android {
compileSdkVersion 29
buildToolsVersion "29.0.2"
defaultConfig {
applicationId "com.example.loyaltybusiness"
minSdkVersion 21
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
//packagingOptions {
// pickFirst 'META-INF/services/javax.annotation.processing.Processor'
//}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
//Volley Libraries
implementation 'com.android.volley:volley:1.1.1-rc1'
implementation 'androidx.recyclerview:recyclerview-selection:1.0.0'
implementation "androidx.cardview:cardview:1.0.0"
//Glide Libraries
implementation 'com.github.bumptech.glide:glide:4.10.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.10.0'
}
gradle уровня проекта
apply plugin: 'com.android.application'
android {
compileSdkVersion 29
buildToolsVersion "29.0.2"
defaultConfig {
applicationId "com.example.loyaltybusiness"
minSdkVersion 21
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
//packagingOptions {
// pickFirst 'META-INF/services/javax.annotation.processing.Processor'
//}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
//Volley Libraries
implementation 'com.android.volley:volley:1.1.1-rc1'
implementation 'androidx.recyclerview:recyclerview-selection:1.0.0'
implementation "androidx.cardview:cardview:1.0.0"
//Glide Libraries
implementation 'com.github.bumptech.glide:glide:4.10.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.10.0'
}
Ожидаемый результат: предприятия, которые будут перечислены в представлении переработчика представления карты нафизическое устройство
Фактический результат: приложение запускается, не вылетает, просто нетна экране приложений он просто пуст, как будто данные json не передаются.