I am creating fragments inside Android Studio where one of my fragments calls an API and displays the listview with a custom listadapter. However, I have read many similar examples but none can determine why my listview is not appearing.
This is my News Fragment:
package com.example.firebasetestapplication;
import android.content.Context;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import android.os.Handler;
import android.os.Looper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import android.widget.TextView;
import com.example.firebasetestapplication.databinding.FragmentNewsBinding;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
/**
* A simple {@link Fragment} subclass.
* Use the {@link NewsFragment#newInstance} factory method to
* create an instance of this fragment.
*/
public class NewsFragment extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
private Handler mHandler = new Handler(Looper.getMainLooper());
ArrayList<News> newsArrayList = new ArrayList<>();
// FragmentNewsBinding binding;
// Context thiscontext;
public NewsFragment() {
// Required empty public constructor
}
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment NewsFragment.
*/
// TODO: Rename and change types and number of parameters
public static NewsFragment newInstance(String param1, String param2) {
NewsFragment fragment = new NewsFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_news,container,false);
TextView textview = v.findViewById(R.id.textview);
ListView listview = v.findViewById(R.id.listview);
// thiscontext = container.getContext();
textview.setText("");
// textView.setText("Trying for the first time");
// Inflate the layout for this fragment
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("https://api.jsonbin.io/v3/b/636b51910e6a79321e444107")
.get()
.build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(@NonNull Call call, @NonNull IOException e) {
e.printStackTrace();
}
@Override
public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
if(response.isSuccessful()) {
String myResponse = response.body().string();
try {
JSONObject jsonObject = new JSONObject(myResponse);
JSONObject record = jsonObject.getJSONObject("record");
JSONArray club_news = record.getJSONArray("Club_News");
Gson gson = new Gson();
Type listType = new TypeToken<ArrayList<News>>(){}.getType();
List<News> total_News = gson.fromJson(club_news.toString(),listType);
for(News news : total_News) {
textview.append("Club: " + news.club + " " + news.description + "\n");
newsArrayList.add(news);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
});
ListAdapter listAdapter = new ListAdapter(getActivity(),newsArrayList);
listview.setAdapter(listAdapter); // line that breaks program
// mHandler.post(new Runnable() {
// @Override
// public void run() {
// ListAdapter listAdapter = new ListAdapter(getActivity(),newsArrayList);
// listview.setAdapter(listAdapter); // line that breaks program
// }
// });
// getActivity().runOnUiThread(new Runnable() {
// @Override
// public void run() {
// ListAdapter listAdapter = new ListAdapter(getActivity(),newsArrayList);
// listview.setAdapter(listAdapter); // line that breaks program
// }
// });
return v;
}
}
The OkHttpRequest successfully gets all the data and organized with Gson. This is my ListAdapter:
package com.example.firebasetestapplication;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.util.ArrayList;
public class ListAdapter extends ArrayAdapter<News> {
public ListAdapter(@NonNull Context context, ArrayList<News> newsArrayList) {
super(context,R.layout.custom_news_item,newsArrayList);
}
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
View listItemView = convertView;
News news = getItem(position);
if(listItemView == null) {
listItemView = LayoutInflater.from(getContext()).inflate(R.layout.custom_news_item,parent,false);
}
ImageView club_logo = listItemView.findViewById(R.id.club_logo);
TextView club = listItemView.findViewById(R.id.club);
TextView club_description = listItemView.findViewById(R.id.club_description);
TextView title = listItemView.findViewById(R.id.title);
TextView description = listItemView.findViewById(R.id.description);
TextView time = listItemView.findViewById(R.id.time);
club_logo.setImageResource(R.drawable.frats_color); // Temporary
club.setText(news.getClub());
club_description.setText(news.getClub_description());
title.setText(news.getTitle());
description.setText(news.getDescription());
time.setText(news.getTime());
return listItemView;
}
}
And my News class Model:
package com.example.firebasetestapplication;
public class News {
String club;
String club_description;
String title;
String description;
String time;
public News(String club, String club_description, String title, String description, String time) {
this.club = club;
this.club_description = club_description;
this.title = title;
this.description = description;
this.time = time;
}
public String getClub() {return club;}
public String getClub_description() {return club_description;}
public String getTitle() {return title;}
public String getDescription() {return description;}
public String getTime() {return time;}
public void setClub(String club) {this.club = club;}
public void setClub_description(String club_description) {this.club_description = club_description;}
public void setTitle(String title) {this.title = title;}
public void setDescription(String description) {this.description = description;}
public void setTime(String time) {this.time = time;}
}
Finally, here is my custom_news item 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="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp">
<LinearLayout
android:id="@+id/first_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginVertical="3dp">
<ImageView
android:id="@+id/club_logo"
android:layout_width="50dp"
android:layout_height="50dp"
android:src="@drawable/frats_color"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:orientation="vertical">
<TextView
android:id="@+id/club"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="0dp"
android:textSize="20sp"
android:textColor="@color/black"
android:textStyle="bold"
android:text="Frater Sodalis" />
<TextView
android:id="@+id/club_description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Social Club at Abilene Christian University"
android:textStyle="italic"/>
</LinearLayout>
</LinearLayout>
<TextView
android:id="@+id/time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:padding="15dp"
android:text="8:15pm" />
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/first_layout"
android:layout_marginTop="0dp"
android:layout_marginStart="10dp"
android:textSize="15sp"
android:textColor="@color/black"
android:textStyle="bold"
android:text="Haunted Forrest is now open! 6869 E North " />
<TextView
android:id="@+id/description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/title"
android:layout_marginTop="10dp"
android:layout_marginStart="10dp"
android:layout_marginBottom="10dp"
android:textSize="15sp"
android:text="@string/HF_Example"/>
</RelativeLayout>
</LinearLayout>
and my fragment_news xml:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".NewsFragment">
<!-- TODO: Update blank fragment layout -->
<TextView
android:id="@+id/textview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:textStyle="bold"
android:text="News Fragment" />
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/listview"
tools:listitem="@layout/custom_news_item" />
</FrameLayout>
I know if looks like a lot, but I am pretty sure that the error lies around the ListAdapter or the News Fragment. I was looking into whether the getActivity() was passing the correct context for the Fragment or whether my listview.setAdapter(listAdapter);
needs a RunOnUiThread somehow in a fragment.
I would very much appreciate it if someone could give me a hint on what's missing for my listview. I know I am pretty close. Thank you so much!
Just in case you are wondering, the Main Activity looks like this:
package com.example.firebasetestapplication;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.os.Bundle;
import android.text.format.DateFormat;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import com.example.firebasetestapplication.databinding.ActivityMainBinding;
import com.firebase.ui.database.FirebaseListAdapter;
import com.firebase.ui.database.FirebaseListOptions;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
public class MainActivity extends AppCompatActivity {
private TextView greetings;
private Button logout;
//Firebase
FirebaseAuth mAuth = FirebaseAuth.getInstance();
private FirebaseListAdapter<ChatMessage> adapter;
private FirebaseUser user;
private FirebaseUser currentUser;
private DatabaseReference reference;
// Binding
ActivityMainBinding binding;
//Assets
private FloatingActionButton fab;
private String userID;
@SuppressLint("MissingInflatedId")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
replaceFragment(new HomeFragment());
//
binding.bottomNavigationView.setOnItemSelectedListener(item -> {
switch (item.getItemId()) {
case R.id.home:
replaceFragment(new HomeFragment());
case R.id.profile:
break;
case R.id.settings:
break;
case R.id.news:
// startActivity(new Intent(MainActivity.this, NewsActivity.class));
replaceFragment(new NewsFragment());
}
return true;
});
logout = findViewById(R.id.signOut);
// greetings = findViewById(R.id.greeting);
currentUser = mAuth.getCurrentUser();
// fab = findViewById(R.id.fab);
//
// fab.setOnClickListener(new View.OnClickListener() {
// @Override
// public void onClick(View view) {
// EditText input = findViewById(R.id.input);
// FirebaseDatabase.getInstance()
// .getReference()
// .push()
// .setValue(new ChatMessage(input.getText().toString(),
// FirebaseAuth.getInstance()
// .getCurrentUser()
// .getDisplayName())
// );
//
// // Clear the input
// input.setText("");
// }
// });
logout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
FirebaseAuth.getInstance().signOut();
startActivity(new Intent(MainActivity.this, LoginActivity.class));
}
});
if (currentUser == null)
{
Intent intent
= new Intent(MainActivity.this,
LoginActivity.class);
startActivity(intent);
}
else
{
// displayChatMessages();
user = FirebaseAuth.getInstance().getCurrentUser();
reference = FirebaseDatabase.getInstance().getReference("Users");
userID = user.getUid();
reference.child(userID).addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
User userChat = snapshot.getValue(User.class);
if(userChat != null) {
String fullname = userChat.fullName;
String email = userChat.email;
String age = userChat.age;
// greetings.setText("Welcome, " + fullname + "!");
}
}
@Override
public void onCancelled(@NonNull DatabaseError error) {
Toast.makeText(MainActivity.this, "Something did not go right!", Toast.LENGTH_SHORT).show();
}
});
}
}
private void replaceFragment(Fragment fragment) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.frame_layout, fragment);
fragmentTransaction.commit();
}
}