I am trying to get an ArrayList from an activity and then display it inside a fragment in a custom adapter. The problem it's that I cannot setAdapter to do so. The error it says the context it's wrong, when I created the Adapter.
Creare_istoricAdapter class:
public class Creare_istoricAdapter extends ArrayAdapter<Creare_istoric> {
private static final String TAG = "Creareistoric_adapter";
private Context mContext;
int mResource;
public Creare_istoricAdapter(#NonNull Context context, int resource, #NonNull ArrayList<Creare_istoric> objects) {
super(context, resource, objects);
mContext = context;
mResource = resource;
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
String id_alerta = getItem(position).getId_alerta();
String tip_problema = getItem(position).getTip_problema();
String data_ora= getItem(position).getData_ora();
String stare_problema = getItem(position).getStare_problema();
String descriere = getItem(position).getDescriere();
Creare_istoric istoric = new Creare_istoric(id_alerta, tip_problema, data_ora, stare_problema, descriere);
LayoutInflater inflater = LayoutInflater.from(mContext);
convertView = inflater.inflate(mResource, parent, false);
TextView text_tip_alerta_istoric = convertView.findViewById(R.id.text_tip_alerta_istoric);
TextView text_ora_alerta_istoric = convertView.findViewById(R.id.text_ora_alerta_istoric);
TextView text_stare_alerta_istoric = convertView.findViewById(R.id.text_stare_alerta_istoric);
text_tip_alerta_istoric.setText(tip_problema);
text_ora_alerta_istoric.setText(data_ora);
text_stare_alerta_istoric.setText(stare_problema);
return convertView;
}
}
The fragment class:
public class Fragment_alerte_trimise extends Fragment {
public Fragment_alerte_trimise(){}
ListView list_view_alerte_trimise;
ArrayList<Creare_istoric> alerteTrimise= new ArrayList<>();
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
View alerte_trimise = inflater.inflate(R.layout.fragment_alerte_trimise,container, false);
return alerte_trimise;
Bundle bundle_trimise;
if (bundle_trimise != null) {
alerteTrimise = bundle_trimise.getParcelableArrayList("alerte_trimise");
}
list_view_alerte_trimise =getView().findViewById(R.id.list_view_alerte_trimise);
Creare_istoricAdapter adapter = new Creare_istoricAdapter(this, R.layout.istoric_alerte_adapter, alerteTrimise);
list_view_alerte_trimise.setAdapter(adapter);
}
}
The problems it's in new Creare_istoricAdapter(this, R.layout.istoric_alerte_adapter, alerteTrimise) , about the context, and is also greyed out, saying it's redundant.
EDIT:
I have changed the code following the answers below, but now when I open the activity that uses the fragment, it does not show the list at all. It's only an blank screen.
The fragment code:
public class Fragment_alerte_trimise extends Fragment {
public Fragment_alerte_trimise(){}
private ListView list_view_alerte_trimise;
ArrayList<Creare_istoric> alerteTrimise= new ArrayList<>();
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
View alerte_trimise = inflater.inflate(R.layout.fragment_alerte_trimise,container, false);
return alerte_trimise;
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Bundle bundle_trimise = getArguments();
if (bundle_trimise != null) {
alerteTrimise = bundle_trimise.getParcelableArrayList("alerte_trimise");
}
list_view_alerte_trimise =getView().findViewById(R.id.list_view_alerte_trimise);
list_view_alerte_trimise.setAdapter(new Creare_istoricAdapter(getContext(), R.layout.istoric_alerte_adapter, alerteTrimise));
}
}
The way I created the Parceable:
Bundle bundle_trimise = new Bundle();
bundle_trimise.putParcelableArrayList("alerte_trimise", alerteTrimise);
Fragment_alerte_trimise fg = new Fragment_alerte_trimise();
fg.setArguments(bundle_trimise);
I have the ListView created in the layout that's inflated by the onCreateView, but when I use getView().findViewById it says that it may produce 'NullPointerException', and so does the getContext(), which says it might be null
Please try to use getContext() instead of this.
You have to use activity context instead of fragment context this. Instead of using getContext() or getActivity() you should initialize the context on onAttach to avoid NullPointerException. Check below:
private Context activityContext;
#Override
public void onAttach(#NonNull Context context) {
super.onAttach(context);
activityContext = context;
}
#Override
public void onDetach() {
super.onDetach();
activityContext = null;
}
Beside this, you have to return the view inside onCreateView at the very end. Check below:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
....
// use alerte_trimise instead of getView()
list_view_alerte_trimise = alerte_trimise.findViewById(R.id.list_view_alerte_trimise);
//use activityContext instead of this
Creare_istoricAdapter adapter = new Creare_istoricAdapter(activityContext, R.layout.istoric_alerte_adapter, alerteTrimise);
....
return alerte_trimise;
}
In your code, you try to use Bundle after call return. That's why rest of your code is unreachable.
You are using Creare_istoricAdapter in your Fragment_alerte_trimise so it needs context. therefor we can give activity context or application context(beyond the activity level)
Moreover...
getContext() - Returns the context view only current running activity.
getActivity()- Return the Activity this fragment is currently associated with.
getActivity() can be used in a Fragment for getting the parent Activity of the Fragment.
Add this code changes to your code.
getActivity().getApplicationContext()
Use getContext() instead of this. this refers to current object (Fragment), which is not subclass of Context.
Create adapter in onViewCreated(), because getContext() returns null in onCreateView().
Related
I want to pass image uri from my array images[] at 0 position to other fragment.
This is my fragment from which i want to pass in onclick method at postion==0.
public class OrganicAcidFragment extends Fragment {
String[] product_name={"Formic Acid","Acetic Acid","Propionic Acid",};
String[] product_cn={"CH2O2","CH3COOH","C3H602"};
int[] images={R.drawable.formicacid,R.drawable.aceticacidjpg,R.drawable.propionicacid};
ListView list;
String quantity;
String price;
FragmentManager fm;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
View rootview = inflater.inflate(R.layout.i_fragment_organic_acid, container, false);
fm=getFragmentManager();
MyAdapter adapter=new MyAdapter(getActivity(),product_name,images,product_cn,quantity,price);
list.setAdapter(adapter);
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if(position==0){
PurchaseFragment ldf = new PurchaseFragment ();
Bundle args = new Bundle();
args.putString("product_name", product_name[0]);
args.putString("product_cn", product_cn[0]);
ldf.setArguments(args);
getFragmentManager().beginTransaction().add(R.id.content_frame, ldf).commit();
}
if(position==1){
fm.beginTransaction().replace(R.id.content_frame,new OrganicBaseFragment()).addToBackStack("chemicalorganicfragment").commit();
}
if(position==2){
fm.beginTransaction().replace(R.id.content_frame,new OrganicBaseFragment()).addToBackStack("chemicalorganicfragment").commit();
}
}
});
return rootview;
}
}
In this fragment i want to get that data:
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
View rootview = inflater.inflate(R.layout.i_fragment_purchase, container, false);
String product_names = getArguments().getString("product_name");
String product_cns = getArguments().getString("product_cn");
imagee=(ImageView)rootview.findViewById(R.id.productimage);
cancel= (Button) rootview.findViewById(R.id.cancel);
address= (EditText) rootview.findViewById(R.id.address);
name.setText(product_names);
cn.setText("("+product_cns+")");
return rootview;
}
Both fragments are in same activity.
How can i do it?
I think best and easiest way to send data between running activities and fragments is LocalBroadcast.
Intent intent = new Intent("some_name");
intent.putExtra("some_data_key", "some_data_value");
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent);
This is how to send local broadcast.
For listen local broadcast you must register that broadcast in onCreate() (If listener is Activity) or onCreateView() (If listener is fragment) or whenever you want to receive that broadcast:
LocalBroadcastManager.getInstance(this/*here is context*/).registerReceiver(someReceiver,
new IntentFilter("some_name"));
This is broadcast receiver to receive data:
BroadcastReceiver someReceiver= new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String data= intent.getStringExtra("some_data_key");
//Here do whatever you want with data
//It isn't must be a string. If you want to send a object you must make object class implement Parcelable properly.
}
};
In the end, don't forget to unregister this broadcast receiver. Do it in onDestroy() or whereever you want.
LocalBroadcastManager.getInstance(this).unregisterReceiver(someReceiver);
You can use bundle to send data from one fragment to another.
//Put the value
YourNewFragment ldf = new YourNewFragment ();
Bundle args = new Bundle();
args.putString("YourKey", "YourValue");
ldf.setArguments(args);
//Inflate the fragment
getFragmentManager().beginTransaction().add(R.id.container, ldf).commit();
In onCreateView() of another fragment:
//Retrieve the value
String value = getArguments().getString("YourKey");
I have a fragment which doesn't contain anything at the application start, but after the data is loaded it should show the loaded data. I do all my data loading in MainActivity in function onDataLoaded which implements DataLoadedListener. After the data is loaded the function sends the data (ArrayList) as a parameter through the function call (initializeAdapter()). Then, the function initializeAdapter() gets it and initialize custom made adapter (adapter is a global object, initialized in initializeAdapter() and used in onCreateView()).
I guess that I should refresh fragment view after the data is loaded and the adapter is initialized, but I don't know how to do it. I tried in a lot of ways but didn't make it.
onDataLoaded function in MainActivity which calls initializeAdapter()
#Override
public void onDataLoaded(List<Grad> gradovi, List<Ponuda> ponude) {
Spinner spinnerGradovi = (Spinner) findViewById(R.id.gradovi_spinner);
ArrayAdapter<String> adapterGradovi;
List<String> listaGradova = new ArrayList<>();
ArrayList<Ponuda> ponudaArrayList = new ArrayList<Ponuda>();
ponudaLista = ponude;
gradLista = gradovi;
for(Grad grad : gradovi ){
listaGradova.add(grad.getNaziv());
}
for(Ponuda ponuda : ponude){
ponudaArrayList.add(ponuda);
}
adapterGradovi = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, listaGradova);
spinnerGradovi.setAdapter(adapterGradovi);
Fragment fragmentGet = svePonudeFragment;
((SvePonudeFragment)fragmentGet).initializeAdapter(ponudaArrayList);
}
and this is a Fragment
public class SvePonudeFragment extends Fragment {
private RecyclerView rv;
RVAdapter adapter;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.sve_ponude_fragment, container, false);
rv = (RecyclerView) rootView.findViewById(R.id.rv);
LinearLayoutManager llm = new LinearLayoutManager(getActivity());
rv.setLayoutManager(llm);
rv.setAdapter(adapter);
return rootView;
}
public void initializeAdapter(List<Ponuda> preuzetePonude){
adapter = new RVAdapter(preuzetePonude);
//this isn't working
/*FragmentManager manager = getActivity().getSupportFragmentManager();
android.support.v4.app.FragmentTransaction ft = manager.beginTransaction();
ft.detach(this).attach(this).commit();*/
//this is not working, neither
Fragment frg = getFragmentManager().findFragmentByTag("sve_ponude_fragment_tag");
final android.support.v4.app.FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.detach(frg);
ft.attach(frg);
ft.commit();
}
}
I am also interested in how to make an empty adapter which loads if data is not loaded yet? And when the data is loaded to fill out another adapter and use it.
Initialize adapter before you set. If you interested to change you approach I can give suggestions: Create a constructor for you fragment which you can pass the ArrayList. OnCreate or OnCreateView you can initialize the adapter and pass the list into. After setting adapter notifyDataChanges and to check if there is data please use some Logs when you pass the data and before you pass the data. Do not directly blame the adapter or fragment control your data. Besides I suggest you to study more using fragments + RecyclerView. I am posting one example that you can look at but the data load in the fragment.
public class CategoryFragment extends Fragment {
//Class Tag
private static final String TAG = CategoryFragment.class.getSimpleName();
//Fragments base context
private Context mContext;
//RecyclerView widget
private RecyclerView mRecyclerView;
//RecyclerView's Layout Manager
private RecyclerView.LayoutManager mLayourManager;
//RecyclerView's Adapter
private CategoryFragmentAdapter mCategoryFragmentAdapter;
//Category Data List
private ArrayList<Category> mCategoryList;
//Interface object
onCategoryItemClick mCallBackCategory;
#Override
public void onAttach(Context context) {
super.onAttach(context);
//Instantiate base context
mContext = context;
//Instantiate interface
mCallBackCategory = (onCategoryItemClick)getActivity();
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Instantiate Category List
mCategoryList = new ArrayList<Category>();
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
//Custom fragment view instantiating
View view_fragment_category = inflater.inflate(R.layout.fragment_items, container, false);
//Instantiating Fragment's recycler view
mRecyclerView = (RecyclerView) view_fragment_category.findViewById(R.id.recycle_categories);
//Instantiate RecycleView's Layout Manager: LinearLayoutManager is one of the default
mLayourManager = new LinearLayoutManager(mContext);
//Setting layout manager for recycler view
mRecyclerView.setLayoutManager(mLayourManager);
//Retrieve data from server, populate the category data list and set the RecyclerView's adapter
getCategories();
//Instantiate the adapter and push the data
mCategoryFragmentAdapter = new CategoryFragmentAdapter(mContext, mCategoryList);
//RecyclerView item click listener
mCategoryFragmentAdapter.SetOnItemClickListener(new CategoryFragmentAdapter.OnItemClickListener() {
#Override
public void onItemClick(View v , int position) {
//Test display
//Toast.makeText(mContext, mCategoryList.get(position).getId(),Toast.LENGTH_LONG).show();
//Push to Activity method with clicked item ID
mCallBackCategory.proceedToProducts(mCategoryList.get(position).getId());
}
});
return view_fragment_category;
}
I have this class here which calls the method setPoint
public class PointsList extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.listpoints, container, false);
public static class PointCreation extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.point_creation, container, false);
setPoint(view, CREATE);
return view;
}
}
static final void setPoint(View view, int goal) {
final EditText SerialField = (EditText) view.findViewById(R.id.Serial);
if(goal == CREATE) {
Button buttonGuardar = (Button) view.findViewById(R.id.buttonGuardar);
buttonGuardar.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String Serial = SerialField.getText().toString();
pointsList.add(new Serial);
//go back to R.layout.listpoints
}
});
}
}
My goal is after I click the button to add the new Serial to the List, I can go back to the previous menu from
R.layout.point_creation to R.layout.listpoints
To move around fragments I generally use something like this:
Fragment fragment = new PointsList();
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.container, fragment)
.commit();
But inside:
static final void setPoint(View view, int goal)
getActivity().getSupportFragmentManager();
cannot be referenced from a static context, and I don't know how to go around it with making the static class non-static? I've some global flags which I use in the static Classes (have 2 of them) that would be a bit painfull to export since
public class PointCreation(int something) extends Fragment
is something I can't do.
You can get the activity from view:
Activity activity = (Activity)view.getContext()
If you use FragmentActivity (it seems to be so), then cast Context to FragmentActivity (instead of regular Activity) and further you will able to call getSupportFragmentManager()
FragmentActivity activity = (FragmentActivity)view.getContext();
FragmentManager manager = activity.getSupportFragmentManager();
You can use by below code;
private static FragmentActivity myContext;
#Override
public void onAttach(Activity activity) {
myContext = (FragmentActivity) activity;
super.onAttach(activity);
}
You can use myContext as Context
You can't reference from a static to non-static objects. First thing, that comes to mind is to use singleton pattern for your fragment. In other words add to you fragment singleton snippet:
static PointsList instance;
public PointsList getInstace(){
if(instance == null){
instance = new PointsList ();
}
return instance;
}
and in your fragment onCreate method assign it to the instance:
instance = this;
after that you can remove static modifier from setPoint method. And call it from any part of your project like PointsList.getInstance().setPoint();
p.s. what goals from static you have to use? You should use static very carefully, many things can be done through singleton instead of using statics.
I've been searching for a while now, but I can't seem to find an answer to the following question:
Why does onCreateView never get triggered? This code is the code generated by Android Studio when creating a new MainActivity plus some of the code I wrote.
I want to use setTextConfig(...,...,...) to set the text in the text fields. But I can't seem to get them using findviewbyid(R.id....); because v is always null, even getView(); returns null.
public static class PlaceholderFragment extends Fragment {
private View v;
private EditText etCustomerName, etDeviceID;
private Spinner select;
public PlaceholderFragment() {
super();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
v = inflater.inflate(R.layout.fragment_main, container, false);
return v;
}
public void setTextConfig(String customerName, String selectedOption, int deviceID){
View vv = getView();
//init form controls
etCustomerName = (EditText)vv.findViewById(R.id.etCustomerName);
etDeviceID = (EditText)v.findViewById(R.id.etDeviceId);
select = (Spinner)v.findViewById(R.id.select);
etCustomerName.setText(customerName);
ArrayAdapter adapter = (ArrayAdapter)select.getAdapter();
int index = adapter.getPosition(selectedOption);
select.setSelection(index);
etDeviceID = (EditText)getView().findViewById(R.id.etDeviceId);
etDeviceID.setText(Integer.toString(deviceID), TextView.BufferType.EDITABLE);
}
}
If you need more detailed info, just ask :)
I am trying to use the method
public Fragment getItem(int position) {
// getItem is called to instantiate the fragment for the given page.
// Return a DummySectionFragment (defined as a static inner class
// below) with the page number as its lone argument.
Fragment fragment = new MappingPage();
Bundle args = new Bundle();
args.putInt(DummySectionFragment.ARG_SECTION_NUMBER, position + 1);
fragment.setArguments(args);
return fragment;
}
I have written a class called MappingPage(), if I try to use the above method, the fragment I create is of type MappingPage because has been extended and hence throw an error as the function returns a fragment (not a MappingPage Object)
EDIT:I am getting an error when I do
Fragment fragment = new MappingPage();
Eclipse tell me that I need to change fragment to type MappingPage, which means i have to change the return type of the function
two Questions
1) How are you supposed to put your custom fragments into this?
2) Why does the dummySectionFrament return a Fragment Object and not a DummySectionFragment object?
thanks in advance
public static class DummySectionFragment extends Fragment {
/**
* The fragment argument representing the section number for this
* fragment.
*/
public static final String ARG_SECTION_NUMBER = "section_number";
public DummySectionFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main_dummy,
container, false);
TextView dummyTextView = (TextView) rootView
.findViewById(R.id.section_label);
dummyTextView.setText(Integer.toString(getArguments().getInt(
ARG_SECTION_NUMBER)));
return rootView;
}
}
here is my class
public class MappingPage extends Fragment
{
private MapView map;
private MapController myMapController;
public static final String ARG_SECTION_NUMBER = "1";
public MappingPage() {
}
public View onCreateView (LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Context context = new ContextThemeWrapper(getActivity(), R.style.fragment_theme);
//LayoutInflater Inflater = inflater.cloneInContext(context);
View view=inflater.inflate(R.layout.fragment_main_dummy, container, false);
return view;
}
#Override
public void onResume() {
map = (MapView)getActivity().findViewById(R.id.openmapview);
map.setBuiltInZoomControls(true);
myMapController = map.getController();
myMapController.setZoom(15);
super.onResume();
}
}
Regarding your first question, this should work. MappingPage is an indirect instance of the Fragment class, and you can therefore return it.
About question two, the method that you call always returns a specific type, like Fragment in the case of getItem(). However, this can be a subclass of that as well, and if you are sure it is, you can safely cast it to that subclass.