Как использовать setContentView во фрагменте вместо активности

Уважаемые Stackoverflowers :)

AllAssetsFragment открывается из MainActivity. В этом фрагменте у меня возникли проблемы с правильной настройкой setContentView() и getApplicationContext().

Я знаю, что что-то не так. Часть кода работает для обычных действий, но не работает в этом фрагменте.


AllAssetsFragment:

import android.content.Intent;
import android.os.Bundle;

import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.room.Room;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;

import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonArrayRequest;
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 AllAssetsFragment extends Fragment {

    public AllAssetsFragment(){


    }


    private static final String HI = "https://uniqueandrocode.000webhostapp.com/hiren/favouritelist.php";
    private List<AssetsItem>assetsItems;
    private RecyclerView recyclerView;
    AssetsAdapter adapter;

    private JsonArrayRequest request;
    private RequestQueue requestQueue;
    public static FavoritesDatabase favoritesDatabase;
    Button btn;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        return inflater.inflate(R.layout.fragment_allassets, container, false);


        recyclerView = (RecyclerView)getView().findViewById(R.id.recyclerview);
        recyclerView.setHasFixedSize(true);
        // +++ PROBLEM 1: Context doesn't work (same on Problem 3 and 4) +++
        recyclerView.setLayoutManager(new LinearLayoutManager(this));

        assetsItems = new ArrayList<>();
        btn=(Button)getView().findViewById(R.id.favbtn);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                // +++ PROBLEM 2: This code doesn't work to open Fragment from Fragment +++
                startActivity(new Intent(AllAssetsFragment.this, FavoritesFragment.class));
            }


        });
        favoritesDatabase = Room.databaseBuilder(getActivity().getApplicationContext(), FavoritesDatabase.class, "myfavdb").allowMainThreadQueries().build();
        getData();

    }

    private void getData() {
        request = new JsonArrayRequest(HI, new Response.Listener<JSONArray>() {
            @Override
            public void onResponse(JSONArray response) {
                JSONObject jsonObject = null;
                for (int i = 0; i < response.length(); i++) {
                    try {
                        JSONObject ob = response.getJSONObject(i);
                        AssetsItem pr = new AssetsItem(ob.getInt("id"),
                                ob.getString("product_name"),
                                ob.getString("product_img"));
                        assetsItems.add(pr);

                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                }
                setupData(assetsItems);
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {

            }
        });

        // +++ PROBLEM 3: Context doesn't work +++
        requestQueue = Volley.newRequestQueue(this);
        requestQueue.add(request);
    }

    private void setupData(List<AssetsItem>assetsItems){
    adapter=new AssetsAdapter(assetsItems,getActivity().getApplicationContext());
    recyclerView.setAdapter(adapter);
    }
}

А вот и наш второй фрагмент: FavoritesFragment:



import android.os.Bundle;

import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import java.util.List;


/**
 * A simple {@link Fragment} subclass.
 */
public class FavoritesFragment extends Fragment {


    public FavoritesFragment() {

    }

    private RecyclerView rv;
    private FavoritesAdapter adapter;

    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        return inflater.inflate(R.layout.fragment_favorites, container, false);

        rv=(RecyclerView)getView().findViewById(R.id.rec);
        rv.setHasFixedSize(true);
        // +++ PROBLEM 4: doesn't work +++
        rv.setLayoutManager(new LinearLayoutManager(this));

        getFavData();
    }

    private void getFavData(){
        List<FavoritesItem>favoritesItems=AllAssetsFragment.favoritesDatabase.favoritesDao().getFavoritesData();

        adapter = new FavoritesAdapter(favoritesItems,getActivity().getApplicationContext());
        rv.setAdapter(adapter);
    }



}

person Community    schedule 17.04.2020    source источник
comment
Пожалуйста, не помечайте вопросы тегом android-studio только потому, что вы его используете: тег Android Studio следует использовать только, когда у вас есть вопросы о самой IDE, а не о коде, который вы пишете (или хочу написать) в нем. См. когда уместно удалить тег IDE, Как избежать неправильного использования тегов? и руководство по тегам. Вместо этого используйте [android] или другие соответствующие теги.   -  person Zoe    schedule 17.04.2020


Ответы (3)


Это ошибки, которые вы сделали в своем коде.

AllAssetsFragment

  • Переместите строку ниже в конец метода onCreateView(). Это оператор возврата, поэтому он должен быть последним в функции.

    return inflater.inflate(R.layout.fragment_allassets, container, false);
    
  • Вы не можете использовать startActivity(...) для запуска фрагмента. Этот метод предназначен строго для запуска действий. Чтобы узнать, как запустить фрагмент, посмотрите этот замечательный ответ.

  • Замените this на getActivity() в строках ниже:

    recyclerView.setLayoutManager(new LinearLayoutManager(this));
    requestQueue = Volley.newRequestQueue(this);

ИзбранноеФрагмент

  • Замените this на getActivity() в строке ниже:

    rv.setLayoutManager(new LinearLayoutManager(this));

Дополнение:

Чтобы запустить фрагмент внутри активности (в вашем случае MainActivity), выполните следующие действия:

  1. В файле activity_main.xml создайте FrameLayout, в котором будет размещаться ваш фрагмент, вы можете присвоить ему идентификатор: container. Если вы не знаете, как это сделать, просто вставьте код ниже:

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/container" />
    
  2. Если вы хотите запустить фрагмент из действия, просто используйте этот фрагмент кода:

    FragmentTransaction transaction = getFragmentManager().beginTransaction();
    transaction.replace(R.id.container, new AllAssetsFragment());
    transaction.commit();
    
  3. Если вы хотите запустить фрагмент из другого фрагмента, просто используйте этот фрагмент кода:

    FragmentTransaction transaction = getActivity().getFragmentManager().beginTransaction();
    transaction.replace(R.id.container, new AllAssetsFragment());
    transaction.commit();
    
  4. В приведенных выше фрагментах кода, если getFragmentManager() не работает или если вы используете AndroidX, используйте вместо этого getSupportFragmentManager().

person Taslim Oseni    schedule 17.04.2020
comment
Все остальные предложения работали хорошо! Но я понятия не имею, как запустить классы AllAssetsFragment и FavoritesFragment. Важно знать: они уже сделаны с названием в коде ниже. Только эта строчка неправильная, можешь написать мне рабочую? ;) Спасибо! startActivity(getActivity(AllAssetsFragment, FavoritesFragment.class)); - person ; 17.04.2020
comment
Я обновил свой ответ. Я добавил несколько шагов о том, как запускать фрагменты. - person Taslim Oseni; 17.04.2020
comment
Если есть что-то, на чем вы застряли, дайте мне знать. Я объясню. - person Taslim Oseni; 17.04.2020

Не используйте setContentView() внутри фрагментов. Вы должны инициализировать свое представление в onCreateView(), как вы уже это делали.

Что касается контекста приложения, я вижу, что вы передаете его своему адаптеру. Я бы сказал, что вам не нужен контекст приложения, так как контекста фрагмента должно быть достаточно. Вы можете пройти requireContext().

Вам также потребуется настроить RecyclerView и адаптер от onCreateView().

person Minas Mina    schedule 17.04.2020
comment
Спасибо за ваше предложение, я добавил его в код выше, но все еще есть 3 проблемы с контекстом и 1 с открытием фрагмента из существующего фрагмента. Чтобы упростить задачу, я добавил в код выше второй фрагмент. Было бы здорово, если бы вы могли решить эти проблемы! :) - person ; 17.04.2020
comment
@Lulu96 Я согласен с Минасом Мина. В последнее время lint Android Studio рекомендует использовать requireContext для получения контекста. Попробуйте заменить getActivity().getApplicationContext() или this на requireContext(). - person hata; 17.04.2020

Вы не вызываете setContentView во фрагментах, вам нужно возвращать представление в методе onCreateView. вы уже сделали.

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    return inflater.inflate(R.layout.fragment_allassets, container, false);
}

а для getApplicationContext нужно звонить getActivity()

как это

getActivity().getApplicationContext()

person code4rox    schedule 17.04.2020
comment
Спасибо за ваше предложение, я добавил его в код выше, но все еще есть 3 проблемы с контекстом и 1 с открытием фрагмента из существующего фрагмента. - person ; 17.04.2020