I'm building an app that connects to a REST API and retrieves all the Employees in a Database. The app uses a RecyclerView to display all the Employees that are brought back in a CardView. The problem is nothing appears in the RecyclerView, and there is data that is being returned from the REST API.
It is an Android application, built in Java, using Pie for the OS. The project was created using the Basic Activity Template.
My Activity Class
public class ViewAllEmployees extends AppCompatActivity {
private List<Employee> employees;
private RecyclerView rcView;
private EmployeeAdapter adapter;
private Context context;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_all_employees);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
context = this;
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
FetchEmployeesTask async = new FetchEmployeesTask(new AsyncResponse() {
#Override
public void processFinished(List<Employee> output) {
Log.i("Async", "Finished");
}
});
async.execute();
rcView = findViewById(R.id.rcView);
adapter = new EmployeeAdapter(context, employees);
rcView.setAdapter(adapter);
rcView.setLayoutManager(new LinearLayoutManager(context));
}
private class FetchEmployeesTask extends AsyncTask<Void, Void, List<Employee>> {
public AsyncResponse delegate = null;
public FetchEmployeesTask(AsyncResponse asyncResponse){
delegate = asyncResponse;
}
#Override
protected List<Employee> doInBackground(Void... voids) {
return new APIHelper().fetchItems();
}
#Override
protected void onPostExecute(List<Employee> items) {
employees = items;
delegate.processFinished(items);
}
}
public interface AsyncResponse{
void processFinished(List<Employee> output);
}
}
The Employee Adapter for the RecyclerView
public class EmployeeAdapter extends RecyclerView.Adapter<EmployeeAdapter.EmployeeViewHolder> {
private List<Employee> employees;
private final LayoutInflater mInflater;
private Context context;
public int position;
public EmployeeAdapter(Context context, List<Employee> employeeList){
this.context = context;
employees = new ArrayList<>();
mInflater = LayoutInflater.from(context);
employees = employeeList;
}
#NonNull
#Override
public EmployeeViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View mItemView = mInflater.inflate(R.layout.employee_card, viewGroup, false);
return new EmployeeViewHolder(mItemView, this);
}
#Override
public void onBindViewHolder(#NonNull EmployeeViewHolder employeeViewHolder, int i) {
Employee empl = employees.get(i);
employeeViewHolder.name.setText(empl.firstName + empl.lastName);
employeeViewHolder.department.setText(empl.department);
}
#Override
public int getItemCount() {
return employees == null ? 0 : employees.size();
}
class EmployeeViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public final TextView name;
public final TextView department;
private EmployeeAdapter adapter;
private final CardView card;
public EmployeeViewHolder(View itemView, EmployeeAdapter adapter) {
super(itemView);
name = itemView.findViewById(R.id.txtName);
department = itemView.findViewById(R.id.txtDepartment);
card = itemView.findViewById(R.id.cv);
itemView.setOnClickListener(this);
this.adapter = adapter;
}
#Override
public void onClick(View view) {
}
}
}
The APIHelper class
public class APIHelper {
private static final String ENDPOINT = "ENDPOINTADDRESS";
private static final String TAG = "APIHelper";
public byte[] getUrlBytes(String urlSpec) throws IOException{
URL url = new URL(urlSpec);
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
try{
ByteArrayOutputStream out = new ByteArrayOutputStream();
InputStream in = connection.getInputStream();
if(connection.getResponseCode() != HttpURLConnection.HTTP_OK){
return null;
}
int bytesRead = 0;
byte[] buffer = new byte[1024];
while((bytesRead = in.read(buffer)) > 0){
out.write(buffer, 0, bytesRead);
}
out.close();
return out.toByteArray();
}
finally {
connection.disconnect();
}
}
public String getUrlString(String urlSpec) throws IOException{
return new String((getUrlBytes(urlSpec)));
}
private void parseItems(List<Employee> employees, JSONArray jsonBody) throws IOException, JSONException {
JSONArray employeeArray = jsonBody;
for(int i = 0; i < employeeArray.length(); i++){
JSONObject jsonEmployee = employeeArray.getJSONObject(i);
JSONObject job = jsonEmployee.getJSONObject("Job");
Employee emp = new Employee();
//emp.setDepartment(jsonEmployee.getString("DepartmentId"));
emp.setEmail(jsonEmployee.getString("EmailAddress"));
emp.setEmployeeID(jsonEmployee.getString("EmployeeID"));
emp.setFirstName(jsonEmployee.getString("FirstName"));
emp.setLastName(jsonEmployee.getString("LastName"));
emp.setMiddleInitial(jsonEmployee.getString("MiddleInitial"));
emp.setPosition(job.getString("JobTitle"));
emp.setWorkNumber(jsonEmployee.getString("WorkNumber"));
employees.add(emp);
}
}
public List<Employee> fetchItems(){
List<Employee> employees = new ArrayList<>();
try{
String url = Uri.parse(ENDPOINT).buildUpon().build().toString();
String jsonString = getUrlString(url);
Log.i(TAG, "Received JSON: " + jsonString);
JSONArray jsonBody = new JSONArray(jsonString);
parseItems(employees, jsonBody);
}
catch (IOException ioe){
Log.e(TAG, "Failed to fetch items", ioe);
}
catch (JSONException je){
Log.e(TAG, "Failed to parse json:", je);
}
return employees;
}
The Layout for ViewAllEmployees
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context=".ViewAllEmployees"
tools:showIn="#layout/activity_view_all_employees">
<android.support.v7.widget.RecyclerView
android:id="#+id/rcView"
android:layout_width="395dp"
android:layout_height="659dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
The Card View that is in the Recyclerview
<?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="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:padding="16dp">
<android.support.v7.widget.CardView
android:id="#+id/cv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
app:cardElevation="5dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/txtName"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Name"/>
<TextView
android:id="#+id/txtDepartment"
android:layout_width="match_parent"
android:layout_height="127dp"
android:layout_below="#+id/txtName"
android:layout_alignEnd="#+id/txtName"
android:layout_marginTop="-142dp"
android:layout_marginEnd="0dp" />
</RelativeLayout>
</android.support.v7.widget.CardView>
</LinearLayout>
When the App is run, the RecyclerView should populate with CardViews that display an Employees name and their Department. However, it currently displays nothing.
You have to notify your adapter after populating your array list. Initialize your employee array list variable,then Do:
private class FetchEmployeesTask extends AsyncTask<Void, Void, List<Employee>> {
public AsyncResponse delegate = null;
public FetchEmployeesTask(AsyncResponse asyncResponse){
delegate = asyncResponse;
}
#Override
protected List<Employee> doInBackground(Void... voids) {
return new APIHelper().fetchItems();
}
#Override
protected void onPostExecute(List<Employee> items) {
employees.addAll(items);
adapter.notifyDataSetChanged();
delegate.processFinished(items);
}
}
FetchEmployeesTask async = new FetchEmployeesTask(new AsyncResponse() {
#Override
public void processFinished(List<Employee> output) {
Log.i("Async", "Finished");
employees.addAll(items);
adapter.notifyDataSetChanged();
}
});
Related
I am a new application developer android app and need some help Please.
I need to know how to add the like button inside (Recyclerview) linked to a database (Mysql) and connect through a Volley library to save all user likes.And see how many likes each topic has.
An example that is in the picture..
I need to add it to this attached project.
MainActivity
public class MainActivity extends AppCompatActivity {
List<RecyclerViewData> recyclerViewDataList;
RecyclerView recyclerView;
private RVAdapter rvAdapter;
private static final String TAG="apple";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setTitle("Employee List");
recyclerViewDataList=new ArrayList<>();
recyclerView=findViewById(R.id.recyclerView);
LinearLayoutManager linearLayoutManager=new LinearLayoutManager(this);
recyclerView.setLayoutManager(linearLayoutManager);
MakeVolleyConnection();
}
private void MakeVolleyConnection() {
recyclerViewDataList = new ArrayList<>();
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET,
"http://10.0.13.45/v/parsing.php", null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
JSONArray dataArray = response.getJSONArray("data");
for (int i = 0; i < dataArray.length(); i++) {
JSONObject userData = dataArray.getJSONObject(i);
RecyclerViewData recyclerViewData = new RecyclerViewData();
recyclerViewData.setId(userData.getInt("id"));
recyclerViewData.setFirstname(userData.getString("first_name"));
recyclerViewData.setLastname(userData.getString("last_name"));
recyclerViewData.setAvatar(userData.getString("avatar"));
recyclerViewDataList.add(recyclerViewData);
}
rvAdapter = new RVAdapter(recyclerViewDataList, MainActivity.this);
recyclerView.setAdapter(rvAdapter);
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(MainActivity.this, ""+error.networkResponse,Toast.LENGTH_SHORT).show();
}
});
MySingleton.getInstance(this).addToRequestQueue(jsonObjectRequest);
}
}
MySingleton
public class MySingleton {
private static MySingleton mInstance;
private RequestQueue mRequestQueue;
private static Context mContext;
private MySingleton(Context context){
// Specify the application context
mContext = context;
// Get the request queue
mRequestQueue = getRequestQueue();
}
public static synchronized MySingleton getInstance(Context context){
// If Instance is null then initialize new Instance
if(mInstance == null){
mInstance = new MySingleton(context);
}
// Return MySingleton new Instance
return mInstance;
}
public RequestQueue getRequestQueue(){
// If RequestQueue is null the initialize new RequestQueue
if(mRequestQueue == null){
mRequestQueue = Volley.newRequestQueue(mContext.getApplicationContext());
}
// Return RequestQueue
return mRequestQueue;
}
public<T> void addToRequestQueue(Request<T> request){
// Add the specified request to the request queue
getRequestQueue().add(request);
}
}
RecyclerViewData
public class RecyclerViewData {
private int id;
private String firstname;
private String lastname;
private String avatar;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getFirstname() {
return firstname;
}
public void setFirstname(String firstname) {
this.firstname = firstname;
}
public String getLastname() {
return lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
public String getAvatar() {
return avatar;
}
public void setAvatar(String avatar) {
this.avatar = avatar;
}
}
RVAdapter
public class RVAdapter extends RecyclerView.Adapter<RVAdapter.RVHOLDER> {
List<RecyclerViewData> recyclerViewDataList;
Context mContext;
// Constructor with List and Context which we'll pass from RecyclerView Activity after a connection to Volley. And application context for the listener that we'll implement this later.
public RVAdapter(List<RecyclerViewData> recyclerViewDataList, Context mContext) {
this.recyclerViewDataList = recyclerViewDataList;
this.mContext = mContext;
}
// Override the method onCreateViewHolder, which will call the custom view holder that needs to be initialized. We specify the layout that each item to be used, so we can achieve this using Layout Inflator to inflate the layout and passing the output to constructor of custom ViewHolder.
#NonNull
#Override
public RVHOLDER onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View itemView = LayoutInflater.from(mContext).inflate(R.layout.adapter_layout, viewGroup, false);
RVHOLDER rvholder = new RVHOLDER(itemView);
return rvholder;
}
//onBindViewHolder is for specifying the each item of RecyclerView. This is very similar to getView() method on ListView. In our example, this is where you need to set the user's id, name and image.
#Override
public void onBindViewHolder(#NonNull RVHOLDER rvholder, int i) {
rvholder.id.setText("User id is "+recyclerViewDataList.get(i).getId());
rvholder.first_name.setText(recyclerViewDataList.get(i).getFirstname() + " " + recyclerViewDataList.get(i).getLastname());
Picasso.get().load(recyclerViewDataList.get(i).getAvatar()).into(rvholder.avatar);
}
//We need to return the size for RecyclerView as how long a RecyclerView is, Our data is in list so passing data.size() will return the number as long as we have.
#Override
public int getItemCount() {
return recyclerViewDataList.size();
}
//This is CustomView holder that we had discuss it earlier above and inflated it in onCreateView() method. This constructor links with the xml to set the data, which we set into onBindViewHolder().
class RVHOLDER extends RecyclerView.ViewHolder {
TextView id;
private TextView first_name;
private ImageView avatar;
public RVHOLDER(#NonNull View itemView) {
super(itemView);
id = itemView.findViewById(R.id.id);
first_name = itemView.findViewById(R.id.firstname_lastname);
avatar = itemView.findViewById(R.id.avatar);
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.cardview.widget.CardView
android:id="#+id/card_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
card_view:cardCornerRadius="4dp"
card_view:cardUseCompatPadding="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="#+id/avatar"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginRight="16dp"
android:scaleType="fitCenter" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="#+id/firstname_lastname"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:textAppearanceMedium" />
<TextView
android:id="#+id/id"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
</androidx.cardview.widget.CardView>
</RelativeLayout>
<?php
$con=mysqli_connect("localhost","root","root","test");
$sql="SELECT * FROM testtable";
$result=mysqli_query($con,$sql);
$data=array();
while($row=mysqli_fetch_assoc($result)){
$data["data"][]=$row;
}
header('Content-Type:Application/json');
echo json_encode($data);
?>
#Override
public void onBindViewHolder(#NonNull RVHOLDER rvholder, int i) {
rvholder.id.setText("User id is "+recyclerViewDataList.get(i).getId());
rvholder.first_name.setText(recyclerViewDataList.get(i).getFirstname() + " " +
recyclerViewDataList.get(i).getLastname());
Picasso.get().load(recyclerViewDataList.get(i).getAvatar()).into(rvholder.avatar);
if()
}
if (recyclerViewDataList.get(i).getLiked()) {
// liked image
Picasso.get().load(gContextCompat.getDrawable(getActivity(), R.drawable.liked);).into(rvholder.like);
} else {
// without like image
Picasso.get().load(gContextCompat.getDrawable(getActivity(), R.drawable.not_like);).into(rvholder.like);
}
Add like boolean variable in RecyclerViewData Class. Add getter and setter of it. Add two drawables in drawable folder for Like and Not_like. Then Add this logic. Hope this will help. Thanks
#Override
public void onBindViewHolder(#NonNull RVHOLDER rvholder, int i) {
rvholder.id.setText("User id is "+recyclerViewDataList.get(i).getId());
rvholder.first_name.setText(recyclerViewDataList.get(i).getFirstname() + " " + recyclerViewDataList.get(i).getLastname());
Picasso.get().load(recyclerViewDataList.get(i).getAvatar()).into(rvholder.avatar);
Picasso.get().load(gContextCompat.getDrawable(getActivity(), if(recyclerViewDataList.get(i).getLiked())R.drawable.liked else R.drawable.not_like).into(rvholder.like);
}
no image is shown from URL even if i tried one image in onCreate it actually works with the same URL but with the RecyclerView nothing is shown
my On Create Method
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
NetworkUtilites ob=new NetworkUtilites();
ob.execute();
/** moviesArray contains Movies with Description **/
moviesArray=ob.getArrayMovies();
adapter = new RecyclerViewAdapter( this, moviesArray);
mRecyclerView = findViewById(R.id.recycler_view);
mRecyclerView.setAdapter(adapter);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
}
Here is onBindViewHolder function
public void onBindViewHolder(#NonNull ViewHolder holder, final int position) {
/** MoviesArray return description of movie , getPoster_path() path return URL Of the poster film**/
String moviePosterURL= moviesArray.get(position).getPoster_path();
if(!TextUtils.isEmpty(moviePosterURL))
{
Picasso.get().load(moviePosterURL).into(holder.imageView);
}
}
Here is onCreateViewHolder function
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layoul_listitem,parent,false);
ViewHolder holder = new ViewHolder(view);
return holder;
}
Here is ViewHolder function
public class ViewHolder extends RecyclerView.ViewHolder
{
ImageView imageView;
RelativeLayout parentlayout;
public ViewHolder(#NonNull View itemView)
{
super(itemView);
imageView=itemView.findViewById(R.id.image);
parentlayout =itemView.findViewById(R.id.parent_layout);
}
}
layout_listitem.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/parent_layout"
>
<ImageView
android:layout_width="60dp"
android:layout_height="60dp"
android:id="#+id/image"
/>
</RelativeLayout>
activity_main.xml with the Recycler View
<?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.recyclerview.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</RelativeLayout>
NetworkUtilites class
public class NetworkUtilites extends AsyncTask<Void,Void,Void>
{
private static final String MoviesURL="http://api.themoviedb.org/3/movie/popular?api_key=";
private ArrayList <ListItem> arrayMovies =new ArrayList<>();
private String sent=null;
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... strings)
{
try
{
URL url = new URL(MoviesURL);
HttpURLConnection urlConnection=(HttpURLConnection)url.openConnection();
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
sent=StreamtoString(in);
in.close();
}
catch (Exception e)
{
}
return null;
}
#Override
protected void onPostExecute(Void s)
{
super.onPostExecute(s);
}
public String StreamtoString(InputStream inputStream)
{
BufferedReader bureader= new BufferedReader(new InputStreamReader(inputStream));
String line;
String Text = "";
try{
while((line=bureader.readLine())!=null)
{
Text+=line;
}
} catch (Exception e) {
}
return Text;
}
public String getSent() {
return sent;
}
public ArrayList<ListItem> getArrayMovies()
{
try {
JSONObject parentObject;
JSONArray parentArray;
if (!sent.equals(null))
{
parentObject = new JSONObject(sent);
parentArray = parentObject.getJSONArray("results");
System.out.println(parentArray.length());
for (int i = 0; i < parentArray.length(); i++)
{
JSONObject movieDetails = parentArray.getJSONObject(i);
String poster_path="http://image.tmdb.org/t/p/w342";
poster_path += movieDetails.getString("poster_path");
String original_title=movieDetails.getString("original_title");
String overview= movieDetails.getString("overview");
int vote_average=movieDetails.getInt("vote_average");
String release_date=movieDetails.getString("release_date");
ListItem ob= new ListItem(original_title,poster_path,overview,vote_average,release_date);
arrayMovies.add(ob);
}
}
}
catch (Exception e)
{
}
return arrayMovies;
}
}
The application crashes when I tried to retrieve the JSON object to be used from searchActivity.java to searchDetail.java. It seems that the function getInfo() causes this problem. Initially, the list_data in getInfo() has size of 10, however after calling it from the searchActivity.java, the size becomes 0. Thus, may I know what can I do to solve this problem?
DataParser.java
public class DataParser extends AsyncTask<Void,Void,Integer> {
Context c;
ArrayList<Herb> herb=new ArrayList<>();
ArrayList<HashMap<String, String>> list_data = new ArrayList<HashMap<String, String>>();
HashMap<String,String> data = new HashMap<>();
public DataParser(ListView lv){
this.lv = lv;
}
public DataParser(Context c, String jsonData, ListView lv) {
this.c = c;
this.jsonData = jsonData;
this.lv = lv;
}
#Override
protected Integer doInBackground(Void... params) {
return this.parseData();
}
#Override
protected void onPostExecute(Integer result) {
super.onPostExecute(result);
pd.dismiss();
if(result==0)
{
Toast.makeText(c,"Unable To Parse",Toast.LENGTH_SHORT).show();
}else {
//BIND DATA TO LISTVIEW
CustomAdapter adapter=new CustomAdapter(c,herb);
lv.setAdapter(adapter);
}
}
private int parseData()
{
try
{
JSONArray ja=new JSONArray(jsonData);
JSONObject jo=null;
herb.clear();
Herb Herb;
for(int i=0;i<ja.length();i++)
{
jo=ja.getJSONObject(i);
String id=jo.getString("h_id");
String name=jo.getString("h_name");
String imageUrl=jo.getString("h_image");
Herb=new Herb();
Herb.setId(id);
Herb.setName(name);
Herb.setImageUrl(imageUrl);
herb.add(Herb);
data.put("id",id);
data.put("name",name);
data.put("imageUrl",imageUrl);
list_data.add(data);
}
DataStorage.map = getInfo();
return 1;
} catch (JSONException e) {
e.printStackTrace();
}
return 0;
}
public ArrayList<HashMap<String, String>> getInfo(){
return this.list_data = list_data;
}
}
searchActivity.java
public class searchActivity extends AppCompatActivity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_search);
ListView lv= (ListView) findViewById(R.id.HerbListView);
Downloader dl = new Downloader(searchActivity.this,urlAddress,lv);
dl.execute();
final DataParser dp = new DataParser(lv);
lv.setOnItemClickListener (new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
try{
ArrayList<HashMap<String, String>> list_data = DataStorage.map;
String hid = list_data.get(position).get("id");
String name = list_data.get(position).get("name");
String imageUrl = list_data.get(position).get("imageUrl");
Intent intent = new Intent(searchActivity.this, searchDetail.class);
intent.putExtra("id", hid);
intent.putExtra("name", name);
intent.putExtra("imageUrl", imageUrl);
startActivity(intent);
}
catch (NullPointerException e){
e.printStackTrace();
}
}
});
}
}
searchDetail.java
public class searchDetail extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_search_detail);
String name = getIntent().getStringExtra("name");
String imageUrl = getIntent().getStringExtra("imageUrl");
TextView txt1= (TextView) findViewById(R.id.txtHName);
ImageView img= (ImageView) findViewById(R.id.imageHerb);
txt1.setText(name);
Picasso.with(this).load(imageUrl).fit().into(img);
}
}
DataStorage.java
public class DataStorage {
public static ArrayList<HashMap<String,String>> map = new ArrayList<>();
}
activity_search_detail.xml
<?xml version="1.0" encoding="utf-8"?>
<ScrollView 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">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:id="#+id/imageHerb"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_centerHorizontal="true"
android:scaleType="fitXY" />
<TextView
android:id="#+id/lblHName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/imageHerb"
android:paddingTop="10dp"
android:text="Herb Name: " />
<TextView
android:id="#+id/txtHName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/imageHerb"
android:layout_toEndOf="#id/lblHName"
android:paddingTop="10dp"
android:text="TextView" />
</RelativeLayout>
current logcat generated
java.lang.IllegalStateException: Circular dependencies cannot exist in RelativeLayout
P/S: I cant find any circular dependencies in the activity_search_detail.xml
First execute the DataParser class ..new DataParser( lv).execute() or in ur case dp.execute() u are missing this statement.. If you are not executing the AsyncTask class it wont do any task in doInBackground(). Hopefully it will solve your problem.. dp.getinfo() will always return a blank list... make another class called class holdHashmapList {
public static ArrayList<Hashmap<String,String>> map= new ArrayList<>();} and in dataParser class holdHashmapList.map =getInfo();} and in onItemClick listener...Arralist<map<>> = holdHashmapList.map; Your hashmap that u are building will always contain the last last object... in parseData function... so before of data.put("id"); just add data=new HashMap<>();
you have to execute DataParser(dp) in order to populate your list_data in SearchActivity. only initializing DataParser won't populate the list_data.
public class searchActivity extends AppCompatActivity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_search);
ListView lv= (ListView) findViewById(R.id.HerbListView);
Downloader dl = new Downloader(searchActivity.this,urlAddress,lv);
dl.execute();
final DataParser dp = new DataParser(lv);
dp.execute(); // update
lv.setOnItemClickListener (new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long
id) {
try{
ArrayList<HashMap<String, String>> list_data = dp.getInfo();
String hid = list_data.get(position).get("id");
String name = list_data.get(position).get("name");
String imageUrl = list_data.get(position).get("imageUrl");
Intent intent = new Intent(searchActivity.this, searchDetail.class);
intent.putExtra("id", hid);
intent.putExtra("name", name);
intent.putExtra("imageUrl", imageUrl);
startActivity(intent);
}
catch (NullPointerException e){
e.printStackTrace();
}
}
});
}
I am trying to populate CardView's inside a RecyclerView. Though I am able to log all the adapter values(to make sure they are non-empty) I can't populate any in the UI. Here is the Activity Code:
FoodActivity.class
public class FoodActivity extends AppCompatActivity
{
private RecyclerView foodView;
private List<Result> adapter_data;
private CustomPlacesAdapter adapter;
private LinearLayoutManager llm;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_food);
foodView = (RecyclerView)findViewById(R.id.foodRView);
adapter = new CustomPlacesAdapter(adapter_data);
adapter_data = new ArrayList<>();
llm = new LinearLayoutManager(this);
foodView.setLayoutManager(llm);
foodView.setAdapter(adapter);
doGetRequest("restaurants in los angeles airport");
}
private void doGetRequest(final String message)
{
ApiInterfacePlaces apiService =
ApiClientPlaces.getClient().create(ApiInterfacePlaces.class);
Call<PlacesPojo> call = apiService.getValues(message, Util.getKeyForPlaces());
call.enqueue(new Callback<PlacesPojo>()
{
#Override
public void onResponse(Call<PlacesPojo>call, Response<PlacesPojo> response)
{
try
{
Log.e("TAG",""+response.body().toString());
List<Result> response_res = response.body().getResults();
adapter_data = response_res;
adapter.notifyDataSetChanged();
}
catch (Exception e)
{
Toast.makeText(FoodActivity.this, "Check data connection", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onFailure(Call<PlacesPojo> call, Throwable t) {
// Log error here since request failed
Log.e("FAILURE", t.toString());
}
});
}
}
Here is the code to the RecyclerView's adapter:
CustomPlacesAdapter.class
public class CustomPlacesAdapter extends RecyclerView.Adapter<CustomPlacesAdapter.HotelsViewHolder>
{
private DataHolder d2 = new DataHolder();
public class HotelsViewHolder extends RecyclerView.ViewHolder
{
private TextView hotelName;
private Typeface face;
private ImageView hotel_logo;
private Context mcontext;
HotelsViewHolder(View itemView)
{
super(itemView);
mcontext = itemView.getContext();
hotelName = (TextView)itemView.findViewById(R.id.hotelName);
face = Typeface.createFromAsset(itemView.getContext().getAssets(), "Fonts/Roboto-Regular.ttf");
hotelName.setTypeface(face);
hotel_logo = (ImageView)itemView.findViewById(R.id.logoOfHotel);
}
}
private static class DataHolder
{
List<Result> feeds;
}
public CustomPlacesAdapter(List<Result> feeds)
{
this.d2.feeds = feeds;
}
#Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
}
#Override
public HotelsViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.food_item, viewGroup, false);
HotelsViewHolder pvh = new HotelsViewHolder(v);
return pvh;
}
#Override
public void onBindViewHolder(HotelsViewHolder feedViewHolder, int i)
{
feedViewHolder.hotelName.setText(d2.feeds.get(i).getName());
Picasso.with(feedViewHolder.mcontext).load(d2.feeds.get(i).getIcon()).into(feedViewHolder.hotel_logo);
}
#Override
public int getItemCount()
{
if(d2.feeds!=null)
{
return d2.feeds.size();
}
else
{
return 0;
}
}
}
This is the CardView that I use:
food_item.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_centerHorizontal="true"
app:cardCornerRadius="5dp"
android:layout_height="100dp"
card_view:cardUseCompatPadding="false"
android:id="#+id/cv">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/logoOfHotel"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/hotelName"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
</android.support.v7.widget.CardView>
Cross checked many things, still unable to fix the issue, what is possibly causing this? Any help would be much appreciated.
I am not getting the desired output from the code.
I used XML DOM parsing to fetch title, pubdate, description and image from link: http://autosportsindia.com/feed
Through the code written no output is obtained. Even though Logcat shows that data is being fetched from the link.
Kindly tell me what is the fault in my code. Suggest any other method of XML parsing with code or link.
public class MainActivity extends AppCompatActivity implements ResultsCallBack {
PlaceholderFragment taskFragment;
ListView articlesListView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
taskFragment = new PlaceholderFragment();
getSupportFragmentManager().beginTransaction().add(taskFragment, "MyFragment").commit();
} else {
taskFragment = (PlaceholderFragment) getSupportFragmentManager().findFragmentByTag("MyFragment");
}
taskFragment.startTask();
articlesListView = (ListView) findViewById(R.id.articlesListView);
}
#Override
public void onPreExecute() {
}
#Override
public void onPostExecute(ArrayList<HashMap<String, String>> results) {
articlesListView.setAdapter(new MyAdapter(this, results));
}
public static class PlaceholderFragment extends Fragment {
AutoSportsIndia downloadTask;
ResultsCallBack callBack;
public PlaceholderFragment() {
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
callBack = (ResultsCallBack) activity;
if(downloadTask!=null)
{
downloadTask.onAttach(callBack);
}
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setRetainInstance(true);
}
public void startTask() {
if (downloadTask != null) {
downloadTask.cancel(true);
} else {
downloadTask = new AutoSportsIndia(callBack);
downloadTask.execute();
}
}
#Override
public void onDetach() {
super.onDetach();
callBack = null;
if(downloadTask!=null) {
downloadTask.onDetach();
}
}
}
public static class AutoSportsIndia extends AsyncTask<Void, Void, ArrayList<HashMap<String, String>>> {
ResultsCallBack callBack =null;
public AutoSportsIndia(ResultsCallBack callBack) {
this.callBack = callBack;
}
public void onAttach(ResultsCallBack callBack) {
this.callBack = callBack;
}
public void onDetach() {
callBack = null;
}
protected void onPreExecute() {
if(callBack!=null)
{
callBack.onPreExecute();
}
}
#Override
protected ArrayList<HashMap<String, String>> doInBackground(Void... params) {
String downloadURL = "http://autosportsindia.com/feed";
ArrayList<HashMap<String, String>> results = new ArrayList<>();
try {
URL url = new URL(downloadURL);
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("GET");
InputStream inputStream = connection.getInputStream();
processXML(inputStream);
} catch (Exception e) {
L.m(e + "");
}
return results;
}
#Override
protected void onPostExecute(ArrayList<HashMap<String, String>> result) {
if(callBack!=null)
{
callBack.onPostExecute(result);
}
}
public ArrayList<HashMap<String, String>> processXML(InputStream inputStream) throws Exception {
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document xmlDocument = documentBuilder.parse(inputStream);
Element rootElement = xmlDocument.getDocumentElement();
L.m("" + rootElement.getTagName());
NodeList itemsList = rootElement.getElementsByTagName("item");
NodeList itemChildren = null;
Node currentItem = null;
Node currentChild = null;
int count = 0;
ArrayList<HashMap<String, String>> results = new ArrayList<>();
HashMap<String, String> currentMap = null;
for (int i = 0; i < itemsList.getLength(); i++) {
currentItem = itemsList.item(i);
itemChildren = currentItem.getChildNodes();
currentMap = new HashMap<>();
for (int j = 0; j < itemChildren.getLength(); j++) {
currentChild = itemChildren.item(j);
if (currentChild.getNodeName().equalsIgnoreCase("title")) {
currentMap.put("title", currentChild.getTextContent());
String temp="title: "+currentChild.getTextContent();
L.m(temp);
}
if (currentChild.getNodeName().equalsIgnoreCase("pubDate")) {
String temp1="pubDate: "+currentChild.getTextContent();
currentMap.put("pubDate", currentChild.getTextContent());
L.m(temp1);
}
if (currentChild.getNodeName().equalsIgnoreCase("description")) {
currentMap.put("description", currentChild.getTextContent());
String temp="description: "+currentChild.getTextContent();
L.m(temp);
}
if (currentChild.getNodeName().equalsIgnoreCase("media:thumbnail")) {
count++;
if (count == 2) {
L.m(currentChild.getAttributes().item(0).getTextContent());
currentMap.put("imageURL", currentChild.getAttributes().item(0).getTextContent());
}
}
if (currentMap != null && !currentMap.isEmpty()) {
results.add(currentMap);
}
}
count = 0;
}
return results;
}
}
}
interface ResultsCallBack {
public void onPreExecute();
public void onPostExecute(ArrayList<HashMap<String, String>> results);
}
class MyAdapter extends BaseAdapter {
ArrayList<HashMap<String, String>> dataSource = new ArrayList<>();
Context context;
LayoutInflater layoutInflater;
public MyAdapter(Context context, ArrayList<HashMap<String, String>> dataSource) {
this.context = context;
this.dataSource = dataSource;
layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return dataSource.size();
}
#Override
public Object getItem(int position) {
return dataSource.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
MyHolder holder = null;
if(row == null)
{
row = layoutInflater.inflate(R.layout.custom_view, parent, false);
holder = new MyHolder(row);
row.setTag(holder);
}
else
{
holder = (MyHolder)row.getTag();
}
HashMap<String, String> currentItem = dataSource.get(position);
holder.articleTitleText.setText(currentItem.get("title"));
holder.articlePublishedDateText.setText(currentItem.get("pubDate"));
// holder.articleImage.setImageURI(Uri.parse(currentItem.get("imageURL")));
holder.articleDescriptionText.setText(currentItem.get("description"));
return row;
}
}
class MyHolder {
TextView articleTitleText;
TextView articlePublishedDateText;
ImageView articleImage;
TextView articleDescriptionText;
public MyHolder(View view) {
articleTitleText = (TextView)
view.findViewById(R.id.articleTitleText);
articlePublishedDateText = (TextView) view.findViewById(R.id.articlePublishedDate);
articleImage = (ImageView) view.findViewById(R.id.articleImage);
articleDescriptionText = (TextView) view.findViewById(R.id.articleDescriptionText);
}
}
XML pages:-
activity_main.xml
<ListView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/articlesListView"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
custom_view.xml
<TextView
android:id="#+id/articleTitleText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:padding="12dp"
android:text="Title"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="#444"/>
<TextView
android:id="#+id/articlePublishedDate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_below="#+id/articleTitleText"
android:paddingBottom="4dp"
android:paddingLeft="12dp"
android:paddingRight="12dp"
android:paddingTop="4dp"
android:text="Date"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="#444"/>
<View
android:id="#+id/separator1"
android:layout_width="match_parent"
android:layout_height="2dp"
android:layout_below="#+id/articlePublishedDate"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
android:background="#e67e22"/>
<ImageView
android:id="#+id/articleImage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/separator1"
android:scaleType="fitCenter"
android:src="#drawable/ic_launcher"/>
<TextView
android:id="#+id/articleDescriptionText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/articleImage"
android:padding="12dp"
android:text="Description"
android:textColor="#444"/>
The processXML method builds and returns an ArrayList<HashMap<String, String>>.
It is called in the doInBackground method, but the return value is discarded. doInBackground then returns a local results object, which is an empty list.
If you had debugged your way through the processXML and doInBackground methods, you would have seen this. When I asked in a comment whether "you tried debugging your code, stepping through and seeing the values being processed", you obviously didn't.