How to make my Fragment make use of my Activity Data? - java

I have an Activity hosting 3 Fragments, my activity contains some data that I want my first fragment to use.
I tried invoking the following method so that the activity can communicate with the fragment:
FirstFragment fragmentFirst = (FirstFragment)
getSupportFragmentManager().findFragmentById(R.id.firstFragment);
assert fragmentFirst != null;
fragmentFirst.doSomething("some param");
For the activity class and:
public void doSomething(String param) {
// do something in fragment
}
For the fragment class, but it brought out an: Attempt to invoke virtual method 'void com.tex.lightweatherforecast.FirstFragment.doSomething(java.lang.String)' on a null object reference
error at runtime.
My Activity code is:
public class HomeActivity extends AppCompatActivity {
public static String BaseUrl = "http://api.openweathermap.org/";
public static String AppId = "9c547bfc852923c3b30d0d62a5ae35e8";
public static String lat = "9.0574";
public static String lon = "7.4898";
// User Timezone name, current time, current temperature, current condition, sunrise, sunset, temperature, pressure, humidity, wind_speed, visibility, UV Index
TextView time_zone, time_field, current_temp, current_output, rise_time, set_time, temp_out, Press_out, Humid_out, Ws_out, Visi_out, UV_out;
ConstraintLayout constraintLayout;
public static int count=0;
int[] drawable =new int[]{R.drawable.dubai,R.drawable.central_bank_of_nigeria,R.drawable.eiffel_tower,R.drawable.hong_kong,R.drawable.statue_of_liberty};
Timer _t;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
FirstFragment fragmentFirst = (FirstFragment)
getSupportFragmentManager().findFragmentById(R.id.firstFragment);
assert fragmentFirst != null;
fragmentFirst.doSomething("some param");
time_zone = findViewById(R.id.textView9);
time_field = findViewById(R.id.textView4);
current_temp = findViewById(R.id.textView10);
current_output = findViewById(R.id.textView11);
rise_time = findViewById(R.id.textView25);
set_time = findViewById(R.id.textView26);
temp_out = findViewById(R.id.textView28);
Press_out = findViewById(R.id.textView29);
Humid_out = findViewById(R.id.textView30);
Ws_out = findViewById(R.id.textView33);
Visi_out = findViewById(R.id.textView34);
UV_out = findViewById(R.id.textView35);
BottomNavigationView bottomNavigationView = findViewById(R.id.bottomNavigationView);
NavController navController = Navigation.findNavController(this, R.id.fragment);
NavigationUI.setupWithNavController(bottomNavigationView, navController);
findViewById(R.id.button2).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getCurrentData();
constraintLayout = findViewById(R.id.layout);
constraintLayout.setBackgroundResource(R.drawable.dubai);
_t = new Timer();
_t.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() { // run on ui thread
#Override
public void run() {
if (count < drawable.length) {
constraintLayout.setBackgroundResource(drawable[count]);
count = (count + 1) % drawable.length;
}
}
});
}
}, 5000, 5000);
}
void getCurrentData() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BaseUrl)
.addConverterFactory(GsonConverterFactory.create())
.build();
WeatherService service = retrofit.create(WeatherService.class);
Call<WeatherResponse> call = service.getCurrentWeatherData(lat, lon, AppId);
call.enqueue(new Callback<WeatherResponse>() {
#Override
public void onResponse(#NonNull Call<WeatherResponse> call, #NonNull Response<WeatherResponse> response) {
if (response.code() == 200) {
WeatherResponse weatherResponse = response.body();
assert weatherResponse != null;
assert response.body() != null;
time_zone.setText(response.body().getTimezone());
time_field.setText(response.body().getCurrent().getDt());
current_temp.setText(response.body().getCurrent().getTemp() + " ℃");
current_output.setText(response.body().getCurrent().getWeather().get(0).getDescription());
rise_time.setText(response.body().getCurrent().getSunrise() + " AM");
set_time.setText(response.body().getCurrent().getSunset() + " PM");
temp_out.setText(response.body().getCurrent().getTemp() + " ℃");
Press_out.setText(response.body().getCurrent().getPressure() + " hpa");
Humid_out.setText(response.body().getCurrent().getHumidity() + " %");
Ws_out.setText(response.body().getCurrent().getWindSpeed() + " Km/h");
Visi_out.setText(response.body().getCurrent().getVisibility() + " m");
}
}
#Override
public void onFailure(#NonNull Call<WeatherResponse> call, #NonNull Throwable t) {
}
});
}
});
}
}
Any help will be Appreciated

I think you are getting this error because the fragment is not active. and if it's active and this approach worked, it's pretty bad approach, there are other ways in when we use the new LiveData and ViewModel arch style.
If you think that DataSource(LiveData usually) will be needed by children(Fragments) make this DataSource owned by the Parent (activity) and keep watching that DataSource inside the fragment(i.e. make observers of this LiveData inside different fragments)
If you need to make a callback from the Fragment to the activity use Contracts(Interfaces) and implement that contract inside the activity(this contract might contain functions like doSomething()) and call that from inside the fragment like this:
(((ContractName)activity).doSomething(passData))

If you want to pass activity data in your first destination fragment, avoid setting up graph in activity layout file.
Remove graph implementation from activity layout. And implement it as below in activity's onCreate method.
NavController navController = Navigation.findNavController(this, R.id.nav_controller);
Bundle bundle = new Bundle();
bundle.putString("key", "value");
navController.setGraph(navController.getGraph(), bundle);
Update your graph file by referring below code.
<navigation 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:id="#+id/navigation_graph"
app:startDestination="#id/homeFragment">
<fragment android:id="#+id/homeFragment"
android:name="com.java.HomeFragment"
android:label="home_fragment"
tools:layout="#layout/fragment_home">
<argument
android:name="key"
app:argType="string"/>
</fragment>
...
...
</navigation>
In your home fragment, get arguments value.
String data = getArguments().getString("key");

Related

Problem resolving an android.content.res.Resources error

I understand that this error has been addressed severally and I've checked most of them like Android: android.content.res.Resources$NotFoundException: String resource ID #0x5, android.content.res.Resources$NotFoundException: String resource ID to see if I could find a solution to my problem but I couldn't and most of them are hard to understand. I can't tell if my code is an int/string so I don't know exactly what to correct, so I need help.
I got this error at runtime:
android.content.res.Resources$NotFoundException: String resource ID #0x601ee924
at android.content.res.Resources.getText(Resources.java:348)
at android.widget.TextView.setText(TextView.java:5848)
at com.tex.lightweatherforecast.Activity.HomeActivity$1.onResponse(HomeActivity.java:66)
at retrofit2.DefaultCallAdapterFactory$ExecutorCallbackCall$1.lambda$onResponse$0$DefaultCallAdapterFactory$ExecutorCallbackCall$1(DefaultCallAdapterFactory.java:89)
at retrofit2.-$$Lambda$DefaultCallAdapterFactory$ExecutorCallbackCall$1$3wC8FyV4pyjrzrYL5U0mlYiviZw.run(Unknown Source:6)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6819)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:497)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:912)
My codes:
HomeActivity.java
public class HomeActivity extends AppCompatActivity {
public static String BaseUrl = "https://api.openweathermap.org";
public static String AppId = "";
public static String lat = "9.0574";
public static String lon = "7.4898";
// User Timezone name, current time
TextView time_zone, time_field;
ConstraintLayout constraintLayout;
public static int count=0;
int[] drawable =new int[]{R.drawable.dubai,R.drawable.central_bank_of_nigeria,R.drawable.eiffel_tower,R.drawable.hong_kong,R.drawable.statue_of_liberty};
Timer _t;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
time_zone = findViewById(R.id.textView4);
time_field = findViewById(R.id.textView9);
BottomNavigationView bottomNavigationView = findViewById(R.id.bottomNavigationView);
NavController navController = Navigation.findNavController(this, R.id.fragment);
NavigationUI.setupWithNavController(bottomNavigationView, navController);
Retrofit retrofit = new Retrofit.Builder().baseUrl(BaseUrl).addConverterFactory(GsonConverterFactory.create()).build();
WeatherService service = retrofit.create(WeatherService.class);
Call<WeatherResponse> call = service.getCurrentWeatherData(lat, lon, AppId);
call.enqueue(new Callback<WeatherResponse>() {
#Override
public void onResponse(#NonNull Call<WeatherResponse> call, #NonNull Response<WeatherResponse> response) {
if (response.code() == 200) {
WeatherResponse weatherResponse = response.body();
assert weatherResponse != null;
assert response.body() != null;
time_zone.setText(response.body().getTimezone());
time_field.setText(response.body().getCurrent().getDt());
constraintLayout = findViewById(R.id.layout);
constraintLayout.setBackgroundResource(R.drawable.dubai);
_t = new Timer();
_t.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
// run on ui thread
runOnUiThread(() -> {
if (count < drawable.length) {
constraintLayout.setBackgroundResource(drawable[count]);
count = (count + 1) % drawable.length;
}
});
}
}, 5000, 5000);
}
}
#Override
public void onFailure(#NotNull Call<WeatherResponse> call, #NotNull Throwable t) {
}
});
}
}
FirstFragment.java
public class FirstFragment extends Fragment {
public static String BaseUrl = "https://api.openweathermap.org";
public static String AppId = "";
public static String lat = "9.0574";
public static String lon = "7.4898";
// User Timezone name, current time, current temperature, current condition, sunrise, sunset, temperature, pressure, humidity, wind_speed, visibility, UV Index
TextView current_temp, current_output, rise_time, set_time, temp_out, Press_out, Humid_out, Ws_out, Visi_out, UV_out;
// 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;
public FirstFragment() {
// 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 SecondFragment.
*/
// TODO: Rename and change types and number of parameters
public static FirstFragment newInstance(String param1, String param2) {
FirstFragment fragment = new FirstFragment();
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) {
// Inflate the layout for this fragment
View rootView = inflater.inflate(R.layout.fragment_first, container, false);
current_temp = rootView.findViewById(R.id.textView10);
current_output = rootView.findViewById(R.id.textView11);
rise_time = rootView.findViewById(R.id.textView25);
set_time = rootView.findViewById(R.id.textView26);
temp_out = rootView.findViewById(R.id.textView28);
Press_out = rootView.findViewById(R.id.textView29);
Humid_out = rootView.findViewById(R.id.textView30);
Ws_out = rootView.findViewById(R.id.textView33);
Visi_out = rootView.findViewById(R.id.textView34);
UV_out = rootView.findViewById(R.id.textView35);
Retrofit retrofit = new Retrofit.Builder().baseUrl(BaseUrl).addConverterFactory(GsonConverterFactory.create()).build();
WeatherService service = retrofit.create(WeatherService.class);
Call<WeatherResponse> call = service.getCurrentWeatherData(lat, lon, AppId);
call.enqueue(new Callback<WeatherResponse>() {
#Override
public void onResponse(#NonNull Call<WeatherResponse> call, #NonNull Response<WeatherResponse> response) {
if (response.code() == 200) {
WeatherResponse weatherResponse = response.body();
assert weatherResponse != null;
assert response.body() != null;
current_temp.setText(getString(R.string.blank, response.body().getCurrent().getTemp() + " ℃"));
current_output.setText(response.body().getCurrent().getWeather().get(0).getDescription());
rise_time.setText(getString(R.string.blank, response.body().getCurrent().getSunrise() + " AM"));
set_time.setText(getString(R.string.blank, response.body().getCurrent().getSunset() + " PM"));
temp_out.setText(getString(R.string.blank, response.body().getCurrent().getTemp() + " ℃"));
Press_out.setText(getString(R.string.blank, response.body().getCurrent().getPressure() + " hpa"));
Humid_out.setText(getString(R.string.blank, response.body().getCurrent().getHumidity() + " %"));
Ws_out.setText(getString(R.string.blank, response.body().getCurrent().getWindSpeed() + " Km/h"));
Visi_out.setText(getString(R.string.blank, response.body().getCurrent().getVisibility() + " m"));
}
}
#Override
public void onFailure(#NonNull Call<WeatherResponse> call, #NonNull Throwable t) {
t.printStackTrace();
}
});
return rootView;
}
}
In my String.xml:
<string name="blank">%s ℃</string>
android.content.res.Resources$NotFoundException: String resource ID #0x601ee924
at android.content.res.Resources.getText(Resources.java:348)
at android.widget.TextView.setText(TextView.java:5848)
at com.tex.lightweatherforecast.Activity.HomeActivity$1.onResponse(HomeActivity.java:66)
As shown above, the exception is raised in HomeActivity in onResponse() method line (66) where you try to set a text into a TextView.
So, In HomeActivity you've:
time_field.setText(response.body().getCurrent().getDt());
And as per documentation, .getDt() returns an integer, so you can't set it directly to TextView unless you convert it to a String.
To solve this, replace that line of code with one of:
// 1st
time_field.setText(String.valueOf(response.body().getCurrent().getDt()));
// 2nd
time_field.setText("" + response.body().getCurrent().getDt());
You need to cast value of position to String. Concatenating with another String is one of the ways to do it
setText("" + position)

How to Call my Fragment's TextViews and Button from my Activity?

To start with, I'm still new to Android development, I've asked similar questions here before How to make my Fragment make use of my Activity Data? and How to send data from Activity to Fragment?(Android)
But it seems that most people did not quite understand what I mean, so let me explain better.
Suppose I have a TextView:
<TextView
android:id="#+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="#string/current"
android:textColor="#FF3D19"
android:textSize="24sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.498"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
and a Button:
<Button
android:id="#+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="14dp"
android:layout_marginTop="92dp"
android:shadowColor="#FFFFFF"
android:text="Click"
android:textColor="#FF5722"
app:layout_constraintStart_toStartOf="#+id/imageView3"
app:layout_constraintTop_toTopOf="#+id/imageView3" />
in my FirstFragment layout.xml, then i want to call them from my MainActivity i.e current_temp = findViewById(R.id.textView10); to get data i.e current_temp.setText(getString(R.string.blank, response.body().getCurrent().getTemp() + " ℃")); from a weather API and findViewById(R.id.button2).setOnClickListener(new View.OnClickListener() {.
Android Studio will not allow you to just use them like that, so i get this error:
java.lang.NullPointerException: Attempt to invoke virtual method 'void
android.view.View.setOnClickListener(android.view.View$OnClickListener)'
on a null object reference
whenever I run the app. I don't get any other error before running, so the reason is that I've not instantiated any method or maybe callback or interface that will tell the Activity to make use of my fragment's TextViews and Button. So that's what I've been stuck with for days trying to fix, but most people just misunderstood me and started suggesting I should learn ViewModel or LiveData. I watched several tutorials on ViewModel including Codinginflow, they never talked about linking activity to fragment TextViews, they only made a fragment send data to another fragment which is not what I want.
My request is similar to this Android: Can't update textview in Fragment from Activity. NullPointerException tried and failed, So I need step by step procedures on how to apply it.
Full Code:
HomeActivity
public class HomeActivity extends AppCompatActivity {
public static String BaseUrl = "http://api.openweathermap.org/";
public static String AppId = "";
public static String lat = "9.0574";
public static String lon = "7.4898";
// User Timezone name, current time, current temperature, current condition, sunrise, sunset, temperature, pressure, humidity, wind_speed, visibility, UV Index
TextView time_zone, time_field, current_temp, current_output, rise_time, set_time, temp_out, Press_out, Humid_out, Ws_out, Visi_out, UV_out;
ConstraintLayout constraintLayout;
public static int count = 0;
int[] drawable = new int[]{R.drawable.dubai, R.drawable.central_bank_of_nigeria, R.drawable.eiffel_tower, R.drawable.hong_kong, R.drawable.statue_of_liberty};
Timer _t;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
time_zone = findViewById(R.id.textView9);
time_field = findViewById(R.id.textView4);
current_temp = findViewById(R.id.textView10);
current_output = findViewById(R.id.textView11);
rise_time = findViewById(R.id.textView25);
set_time = findViewById(R.id.textView26);
temp_out = findViewById(R.id.textView28);
Press_out = findViewById(R.id.textView29);
Humid_out = findViewById(R.id.textView30);
Ws_out = findViewById(R.id.textView33);
Visi_out = findViewById(R.id.textView34);
UV_out = findViewById(R.id.textView35);
BottomNavigationView bottomNavigationView = findViewById(R.id.bottomNavigationView);
NavController navController = Navigation.findNavController(this, R.id.fragment);
NavigationUI.setupWithNavController(bottomNavigationView, navController);
findViewById(R.id.button2).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getCurrentData();
constraintLayout = findViewById(R.id.layout);
constraintLayout.setBackgroundResource(R.drawable.dubai);
_t = new Timer();
_t.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() { // run on ui thread
#Override
public void run() {
if (count < drawable.length) {
constraintLayout.setBackgroundResource(drawable[count]);
count = (count + 1) % drawable.length;
}
}
});
}
}, 5000, 5000);
}
void getCurrentData() {
Retrofit retrofit = new Retrofit.Builder().baseUrl(BaseUrl).addConverterFactory(GsonConverterFactory.create()).build();
WeatherService service = retrofit.create(WeatherService.class);
Call<WeatherResponse> call = service.getCurrentWeatherData(lat, lon, AppId);
call.enqueue(new Callback<WeatherResponse>() {
#Override
public void onResponse(#NonNull Call<WeatherResponse> call, #NonNull Response<WeatherResponse> response) {
if (response.code() == 200) {
WeatherResponse weatherResponse = response.body();
assert weatherResponse != null;
assert response.body() != null;
time_zone.setText(response.body().getTimezone());
time_field.setText(response.body().getCurrent().getDt());
current_temp.setText(getString(R.string.blank, response.body().getCurrent().getTemp() + " ℃"));
current_output.setText(response.body().getCurrent().getWeather().get(0).getDescription());
rise_time.setText(getString(R.string.blank, response.body().getCurrent().getSunrise() + " AM"));
set_time.setText(getString(R.string.blank, response.body().getCurrent().getSunset() + " PM"));
temp_out.setText(getString(R.string.blank, response.body().getCurrent().getTemp() + " ℃"));
Press_out.setText(getString(R.string.blank, response.body().getCurrent().getPressure() + " hpa"));
Humid_out.setText(getString(R.string.blank, response.body().getCurrent().getHumidity() + " %"));
Ws_out.setText(getString(R.string.blank, response.body().getCurrent().getWindSpeed() + " Km/h"));
Visi_out.setText(getString(R.string.blank, response.body().getCurrent().getVisibility() + " m"));
}
}
#Override
public void onFailure(#NonNull Call<WeatherResponse> call, #NonNull Throwable t) {
}
});
}
});
}
}
FirstFragment
public class FirstFragment 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;
public FirstFragment() {
// 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 SecondFragment.
*/
// TODO: Rename and change types and number of parameters
public static FirstFragment newInstance(String param1, String param2) {
FirstFragment fragment = new FirstFragment();
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) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_first, container, false);
}
}
Taking the whole functionality to Fragment won't work too, because retrofit can only be called from Activity. But if you have any solid suggestions, I'll appreciate it.
I suggest you two ways can update data to Text View of Fragment from Activity.
1. Call method update Text View of fragment from Activity (simple way)
Create a method updateData()in fragment class to update data to Text View.
You declare a fragment parameter in activity class and assign to this parameter when add fragment to activity.
When you receive data from api in activity, call fragment.updateData()
fragment_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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">
<TextView
android:id="#+id/temp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:text="TextView"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/hud"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:text="TextView"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/temp" />
<Button
android:id="#+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
home_activity.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
FirstFragment.kt
class FirstFragment : Fragment(R.layout.fragment_layout) {
private lateinit var temp: TextView
private lateinit var hud: TextView
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
temp = view.findViewById(R.id.temp)
hud = view.findViewById(R.id.hud)
}
fun setDataToView(data: WeatherResponse) {
temp.text = data.temp
hud.text = data.hud
}
}
HomeActivity.kt
class HomeActivity: AppCompatActivity() {
private val fragment = FirstFragment()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.home_activity)
addFragment()
fragment.view?.findViewById<Button>(R.id.button2)?.setOnClickListener {
getCurrentData()
}
}
private fun addFragment(){
val fm = supportFragmentManager
fm.beginTransaction().replace(R.id.container, fragment, "FirstFragment").commit()
}
private fun getCurrentData(){
//Your retrofit code in here. I only show code in onResponse()
//.....
#Override
public void onResponse(#NonNull Call<WeatherResponse> call, #NonNull Response<WeatherResponse> response) {
if (response.code() == 200) {
fragment.setDataToView(response)
}
}
//....
}
}
2. Using ViewModel
Create a SharedViewModel class with a livedata parameter.
In activity, on onCreate() you create a SharedViewModel paramerter like below:
SharedViewModel viewModel = new SharedViewModel(this).get(SharedViewModel .class);
In fragment, on onActivityCreated() you create a SharedViewModel paramerter like below:
SharedViewModel viewModel = new SharedViewModel(requireActivity()).get(SharedViewModel .class);
Finally, you have same ViewModel instance in activity and fragment because both using activity context. When you receive data from api, update your livedata parameter in activity, fragment also receives livedata parameter onChanged event and then you can update Text View.
There are many ways to achieve what you are tying to do, I will be using RxJava.
Add RxJava in your project:
implementation 'io.reactivex.rxjava3:rxandroid:3.0.0'
Create a POJO class to hold your data which then later can be transferred using RxJava bus
public class WeatherReport {
private String time_zone;
private String time_field;
private String current_temp;
private String current_output;
private String rise_time;
private String set_time;
private String temp_out;
private String Press_out;
private String Humid_out;
private String Ws_out;
private String Visi_out;
public String getCurrent_output() {
return current_output;
}
public String getCurrent_temp() {
return current_temp;
}
public String getHumid_out() {
return Humid_out;
}
public String getPress_out() {
return Press_out;
}
public String getRise_time() {
return rise_time;
}
public String getSet_time() {
return set_time;
}
public String getTemp_out() {
return temp_out;
}
public String getTime_field() {
return time_field;
}
public String getTime_zone() {
return time_zone;
}
public String getVisi_out() {
return Visi_out;
}
public String getWs_out() {
return Ws_out;
}
public void setCurrent_output(String current_output) {
this.current_output = current_output;
}
public void setCurrent_temp(String current_temp) {
this.current_temp = current_temp;
}
public void setHumid_out(String humid_out) {
Humid_out = humid_out;
}
public void setPress_out(String press_out) {
Press_out = press_out;
}
public void setRise_time(String rise_time) {
this.rise_time = rise_time;
}
public void setSet_time(String set_time) {
this.set_time = set_time;
}
public void setTemp_out(String temp_out) {
this.temp_out = temp_out;
}
public void setTime_field(String time_field) {
this.time_field = time_field;
}
public void setTime_zone(String time_zone) {
this.time_zone = time_zone;
}
public void setVisi_out(String visi_out) {
Visi_out = visi_out;
}
public void setWs_out(String ws_out) {
Ws_out = ws_out;
}
}
Create a RxJava bus
import io.reactivex.rxjava3.subjects.BehaviorSubject;
public class RxJavaBus {
private static final BehaviorSubject<WeatherReport> behaviorSubject
= BehaviorSubject.create();
public static BehaviorSubject<WeatherReport> getSubject() {
return behaviorSubject;
}
}
Now from your activity(or from wherever you want to transfer data) use RxBus like this:
WeatherReport weatherReport = new WeatherReport();
weatherReport.setCurrent_output("Some DATA");
weatherReport.setCurrent_temp("Some DATA");
weatherReport.setHumid_out("Some DATA");
weatherReport.setPress_out("Some DATA");
weatherReport.setRise_time("Some DATA");
weatherReport.setSet_time("Some DATA");
weatherReport.setTime_field("Some DATA");
weatherReport.setVisi_out("Some DATA");
weatherReport.setTemp_out("Some DATA");
weatherReport.setWs_out("Some DATA");
weatherReport.setTime_zone("some DATA");
RxJavaBus.getSubject().onNext(weatherReport);
Now you receive your data in your fragment (or wherever you want) like this:
RxJavaBus.getSubject().subscribe(weatherReportFromActivity -> {
weatherReportFromActivity.getCurrent_output();
weatherReportFromActivity.getCurrent_temp();
weatherReportFromActivity.getHumid_out();
weatherReportFromActivity.getPress_out();
weatherReportFromActivity.getRise_time();
weatherReportFromActivity.getSet_time();
weatherReportFromActivity.getWs_out();
weatherReportFromActivity.getTime_zone();
weatherReportFromActivity.getVisi_out();
weatherReportFromActivity.getTime_field();
weatherReportFromActivity.getTemp_out();
});
You're getting a NullPointerException because findViewById(R.id.button2) returns null.
You need to use the fragment's view as the root. The activity.findViewById(...) call uses the activity's view as the root - it's searching activity_home.xml, which doesn't have button2. You can access the fragment's version with fragment.getView().findViewById(R.id._), BUT:
You need to make sure that the fragment has at finished its onCreateView() step in the life cycle. So it has to be launched and inflated. Otherwise, again, the button doesn't exist.
You can make sure your setup is called at the right time and with the view by making it a callback in the fragment life cycle.
//This class can be anywhere - it can be global, private inner, anonymous
class SetupCallback extends FragmentLifeCycleCallback {
#Override
void onFragmentViewCreated(FragmentManager fm, Fragment f, View v, Bundle savedInstanceState) {
ButtonView button = v.findViewById(R.id.button2);
if(button != null) { //This gets called for all fragments so check for null
button.setOnClickListener(new OnClickListener {...});
}
//Repeat for any other elements in the view e.g.
TextView someText = v.findViewById(R.id.someTextView);
someText.setText(R.string.message);
}
}
//In the activity setup - I usually put in onCreate()
SupportFragmentManager.supportFragmentManager = getSupportFragmentManager();
supportFragmentManager.registerFragmentLifecycleCallbacks(new SetupCallback());
//anonymous version:
//supportFragmentManager.registerFragmentLifecycleCallbacks(new FragmentLifecycleCallback() { /*contents of class*/ });
Alternatively you could possibly initialise the Retrofit and Weather service in the Activity, pass them in to the fragment with the constructor or a bundle, then use them to setup the onClickListener in onCreateView().
The RxJava and SharedView approaches are alternatives to having a listener stuck on all the fragment life cycle calls, vs having alternative architectures which make the fragment more reactive.
This needs the androidx.lifecycle.common dependency. If you're using gradle that would be:
dependencies {
implementation 'androidx.lifecycle:lifecycle-common:2.3.0-rc1'
}
Create a class to get retrofit client like below
class RetrofitClient {
private Retrofit retrofit;
private String BASE_URL = "";
public ServiceAPI getRetrofitInstance() {
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit.create(WeatherService.class);
}
Now you can call apis inside fragment like this
WeatherService service = RetrofitClient().getRetrofitInstance()
void getCurrentData() {
Call<WeatherResponse> call = service.getCurrentWeatherData(lat, lon, AppId);
call.enqueue(new Callback<WeatherResponse>() {
#Override
public void onResponse(#NonNull Call<WeatherResponse> call, #NonNull Response<WeatherResponse> response) {
if (response.code() == 200) {
WeatherResponse weatherResponse = response.body();
assert weatherResponse != null;
assert response.body() != null;
time_zone.setText(response.body().getTimezone());
time_field.setText(response.body().getCurrent().getDt());
current_temp.setText(getString(R.string.blank, response.body().getCurrent().getTemp() + " ℃"));
current_output.setText(response.body().getCurrent().getWeather().get(0).getDescription());
rise_time.setText(getString(R.string.blank, response.body().getCurrent().getSunrise() + " AM"));
set_time.setText(getString(R.string.blank, response.body().getCurrent().getSunset() + " PM"));
temp_out.setText(getString(R.string.blank, response.body().getCurrent().getTemp() + " ℃"));
Press_out.setText(getString(R.string.blank, response.body().getCurrent().getPressure() + " hpa"));
Humid_out.setText(getString(R.string.blank, response.body().getCurrent().getHumidity() + " %"));
Ws_out.setText(getString(R.string.blank, response.body().getCurrent().getWindSpeed() + " Km/h"));
Visi_out.setText(getString(R.string.blank, response.body().getCurrent().getVisibility() + " m"));
}
}
#Override
public void onFailure(#NonNull Call<WeatherResponse> call, #NonNull Throwable t) {
}
});
}
});
}
Set the data you want to update in the bundle set fragment arguments and call the newInstance then update your views accordingly.
From Activity
FirstFragment.newInstance("yourData","yourData");
In your Fragment
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}

Execute a function on the end of asynctask

i've got a little problem at the moment:
I am trying to make visible 2 buttons on my fragment after the asynktask i called is finished. For that i was using this:
while (!recordi.getterminé){
}
terminé();
But this is not optimal and my app is not responding :(
So is there any solutions to call the function terminé() in the onPostExecute function?
Thanks.
Here is my code:
the fragment:
public class FragmentEnregistrer extends Fragment {
String path,nomfinal, ip="http://MYIP/php";
ImageButton mrecord,mupload,mlire;
TextView Nomm;
ProgressBar progressbar;
int i=2;
EnregistrerSon recordi;
String id;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View myView= inflater.inflate(R.layout.enregistrer, container, false);
mrecord= (ImageButton) myView.findViewById(record);
mupload= (ImageButton) myView.findViewById(upload);
mlire= (ImageButton) myView.findViewById(lire);
Nomm = (TextView) myView.findViewById(NomWhizz);
progressbar = (ProgressBar) myView.findViewById(progressBar);
progressbar.setVisibility(View.INVISIBLE);
id=((MainActivity)getActivity()).getIdentifiant();
mrecord.setOnClickListener(new View.OnClickListener() {
#RequiresApi(api = Build.VERSION_CODES.N)
#Override
public void onClick(View v) {
Toast.makeText(getActivity().getApplicationContext(), "Enregistrement en cours", Toast.LENGTH_SHORT).show();
String nomm = Nomm.getText().toString();
nomm=nomm.replace(" ", "_");
nomm=nomm.replace("&", "");
final String finalNomm = nomm;
recordi = new EnregistrerSon();
recordi.execute(finalNomm);
terminé();
}
});
mupload.setOnClickListener(new View.OnClickListener() {
#RequiresApi(api = Build.VERSION_CODES.N)
#Override
public void onClick(View v) {
UploadOnServer upload = new UploadOnServer();
progressbar.setVisibility(View.VISIBLE);
upload.execute(path,nomfinal);
progressbar.setVisibility(View.INVISIBLE);
HttpGetRequest request = new HttpGetRequest();
request.execute(ip+"/son/creation_son.php?nom_whiz="+nomfinal+"&id_createur="+id);
}
});
mlire.setOnClickListener(new View.OnClickListener() {
#RequiresApi(api = Build.VERSION_CODES.N)
#Override
public void onClick(View v) {
LireSonLocal local = new LireSonLocal();
Uri myUri = Uri.parse("file://"+recordi.getAccess());
local.execute(myUri);
}
});
return myView;
}
#RequiresApi(api = Build.VERSION_CODES.N)
public void terminé(){
Log.i("Enregistrement","terminé");
Toast.makeText(getActivity().getApplicationContext(), "Enregistrement terminé", Toast.LENGTH_LONG).show();
path = recordi.getAccess();
nomfinal = recordi.getNomSansExtenssions();
Log.i("nomfinale",nomfinal);
mlire.setVisibility(View.VISIBLE);
mupload.setVisibility(View.VISIBLE);
Log.i("test","");
}
}
And the asynktask :
class EnregistrerSon extends AsyncTask<String,Void,String> {
private Boolean isRecording = false;
private Boolean termine = false;
private String Nom, NOM;
#RequiresApi(api = Build.VERSION_CODES.N)
#Override
protected String doInBackground(String... params) {
NOM = params[0];
if(!isRecording){
//configuration
Looper.prepare();
MediaRecorder mr = new MediaRecorder();
mr.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
mr.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mr.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
mr.setAudioChannels(1);
mr.setAudioEncodingBitRate(1280000);
mr.setAudioSamplingRate(9500000);
mr.setOutputFile(getAccess());
try {mr.prepare();}
catch (IOException e) {e.printStackTrace();}
//Demarage du record
long start_time = System.currentTimeMillis(); //pendant 15 secondes
long wait_time = 15000;
long end_time = start_time + wait_time;
mr.start();
while (System.currentTimeMillis() < end_time){
Long temps = end_time - System.currentTimeMillis();
isRecording = true;
//pendant 15 secondes
}
mr.stop();
mr.reset();
mr.release();
isRecording = false;
termine = true;
//fin de l'enregistrement
}
return "lol";
}
#RequiresApi(api = Build.VERSION_CODES.N)
protected void onPostExecute(String s) {
super.onPostExecute(s);
}
#TargetApi(Build.VERSION_CODES.N)
#RequiresApi(api = Build.VERSION_CODES.N)
String getAccess(){
MainActivity main = new MainActivity();
if(Objects.equals(NOM, "Nom") || Objects.equals(NOM, "") || NOM == null ) {
Calendar now = Calendar.getInstance();
Nom = now.get(Calendar.HOUR_OF_DAY) + "_" + now.get(Calendar.DAY_OF_MONTH) + "_" + now.get(Calendar.MONTH) + "_" + now.get(Calendar.YEAR);
}
else{
Nom = NOM;
}
File directory = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Whizz/");
directory.mkdirs();
String filename = directory +"/"+Nom+".mp3";
Log.i("filename",filename);
return filename;
}
Boolean getTerminé(){
return termine;
}
String getNomSansExtenssions(){
return Nom;
}
}
To execute your method terminé inside the AsyncTask class. I suggest to have the following:
Create an instance field of FragmentEnregistrer inside your EnregistrerSon class.
private FragmentEnregistrer fragmentEnregistrer;
Create a constructor in your EnregistrerSon class with an expected argument of FragmentEnregistrer class, and assign the argument to the field variable.
public EnregistrerSon(FragmentEnregistrer fe) {
this.fragmentEnregistrer = fe;
}
You can then call the terminé method in the onPostExecute method, as follows:
protected void onPostExecute(String s) {
super.onPostExecute(s);
this.fragmentEnregistrer.terminé();
}
Last, pass the instance of the FragmentEnregistrer object on EnregistrerSon instantiation.
recordi = new EnregistrerSon(FragmentEnregistrer.this);
recordi.execute(finalNomm);
First, line while (!recordi.getterminé){} terminé(); makes no sense, it equals:
while (!recordi.getterminé){
}
terminé();
Regarding onPostExecute, yes, just write the function call in it:
protected void onPostExecute(String s) {
// Anything here will be executed at the end, when doInBackground finishes
terminé();
}
use Broadcast/Receiver pattern, onhandleintent() will run on UI thread where you can make your buttons visible.
1.Start the async task .
2.Define a BroadcastReceiver, instantiate one in your activity and register/unregister it accordingly.
3.In onpostexecute() of async task just call sendBroadcast. You may need to pass a context parameter when instantiating the AsyncTask.
The onHandleIntent method of your app's broadcast receiver (the one you instantiated on step 2) will run on the UI thread, making all those UI updates safe.

Not hide layout when load data in RecyclerView on Android

I want develop application for one website and i want load site posts into RecyclerView. I want show load layout for first entry in application and when load posts data into RecyclerView, hide this layout and show RecyclerView!
I write this codes, but it's not work me and always show emptyLayout.
Main Activity XML :
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/main_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/appBackground"
tools:context=".Activities.Main_page">
<include
android:id="#+id/main_toolbar"
layout="#layout/toolbar" />
<android.support.v7.widget.RecyclerView
android:id="#+id/main_recycler"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/main_toolbar" />
<RelativeLayout
android:id="#+id/main_empty_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone">
<include layout="#layout/empty_page_layout" />
</RelativeLayout>
</RelativeLayout>
MainActivity java :
public class Main_page extends AppCompatActivity {
private static final long RIPPLE_DURATION = 250;
private Toolbar toolbar;
private RelativeLayout root;
private ImageView menu_image;
private RecyclerView main_recyclerView;
private MainAdapter mAdaper;
private List<MainDataModel> dataModels = new ArrayList<MainDataModel>();
private List<MainDataModel> dataModelsArray;
private Context context;
protected Handler handler;
private RelativeLayout loadLayout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_page);
if (!EventBus.getDefault().isRegistered(this)) {
EventBus.getDefault().register(this);
}
handler = new Handler();
context = getApplicationContext();
loadLayout = (RelativeLayout) findViewById(R.id.main_empty_layout);
toolbar = (Toolbar) findViewById(R.id.main_toolbar);
if (toolbar != null) {
setSupportActionBar(toolbar);
getSupportActionBar().setTitle(null);
}
LoadData();
// Menu
root = (RelativeLayout) findViewById(R.id.main_root);
View guillotineMenu = LayoutInflater.from(this).inflate(R.layout.menu_layout, null);
root.addView(guillotineMenu);
menu_image = (ImageView) toolbar.findViewById(R.id.toolbar_logo);
new GuillotineAnimation.GuillotineBuilder(guillotineMenu, guillotineMenu.findViewById(R.id.menu_layout_image), menu_image)
.setStartDelay(RIPPLE_DURATION)
.setActionBarViewForAnimation(toolbar)
.setClosedOnStart(true)
.build();
// RecyclerView and setData
main_recyclerView = (RecyclerView) findViewById(R.id.main_recycler);
main_recyclerView.setHasFixedSize(true);
main_recyclerView.setLayoutManager(new LinearLayoutManager(this));
mAdaper = new MainAdapter(this, dataModels);
main_recyclerView.setAdapter(mAdaper);
if (dataModels.isEmpty()) {
main_recyclerView.setVisibility(View.GONE);
loadLayout.setVisibility(View.VISIBLE);
} else {
main_recyclerView.setVisibility(View.VISIBLE);
loadLayout.setVisibility(View.GONE);
}
}
#Subscribe
public void onEvent(List<MainDataModel> mainInfoModels) {
mAdaper.add(mainInfoModels);
}
private void LoadData() {
final MainDataInfo dataInfo = new MainDataInfo();
dataInfo.getMainDataInfo(this);
}
}
AsyncTask code:
public class MainDataInfo {
private Context mContext;
public void getMainDataInfo(Context context) {
mContext = context;
new getInfo().execute(ServerIP.getIP());
}
private class getInfo extends AsyncTask<String, Void, String> {
EventBus bus = EventBus.getDefault();
private String ou_response;
private List<MainDataModel> infoModels;
#Override
protected void onPreExecute() {
CustomProcessDialog.createAndShow(mContext);
infoModels = new ArrayList<>();
}
#Override
protected String doInBackground(String... params) {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(ServerIP.getIP())
.build();
Response response;
try {
response = client.newCall(request).execute();
ou_response = response.body().string();
response.body().close();
if (ou_response != null) {
try {
JSONObject postObj = new JSONObject(ou_response);
JSONArray postsArray = postObj.getJSONArray("posts");
infoModels = new ArrayList<>();
for (int i = 0; i <= infoModels.size(); i++) {
JSONObject postObject = (JSONObject) postsArray.get(i);
int id = postObject.getInt("id");
String title = postObject.getString("title");
Log.d("Data", "Post id: " + id);
Log.d("Data", "Post title: " + title);
//Use the title and id as per your requirement
infoModels.add(new MainDataModel(
postObject.getInt("id"),
postObject.getString("title"),
postObject.getString("content"),
postObject.getString("thumbnail")));
}
} catch (JSONException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
return ou_response;
}
#Override
protected void onPostExecute(String result) {
CustomProcessDialog.dissmis();
if (result != null) {
bus.post(infoModels);
}
}
}
}
when delete emptyLayout from mainActivity, RecyclerView show all posts. when insert this layout (emptyLayout) recyclerView is not VISIBLE and EmptyLayout is not GONE!
How can i fit this problem? tnx all <3
I presume that you don't make your call at the good place because dataModels is always empty.
Indeed, you have to do your call only after the onPostExecute() method on your AsyncTask which loads your data.
You can use an interface (AsyncResponse in example below) to catch the end of AyncTask process.
Here AynscResponse :
public interface AsyncResponse {
void endTask(List<MainDataModel> dataModels);
}
In your AsyncTask :
private AsyncResponse listener;
#Override
protected void onPostExecute(List<MainDataModel> dataModels) {
listener.processFinish(dataModels);
}
Finally in your activity :
// Set by default the visibility
main_recyclerView.setVisibility(View.GONE);
loadLayout.setVisibility(View.VISIBLE);
public void processFinish(List<MainDataModel> dataModels) {
if (dataModels.isEmpty()) {
// Handle error with an empty list
} else {
main_recyclerView.setVisibility(View.VISIBLE);
loadLayout.setVisibility(View.GONE);
}
}

Can't start Activity from OnClickListener "method startActivity(Intent, int) is undefined for the type"

I am populating a Scrollview using items retrieved from a SQLite database, and am dynamically generating an OnClickListener for each row using the code below. I want the code in the OnClickListener to return control to the Activity which called it (MealActivity) using an Intent, passing back the id of the item which was clicked on.
I've attempted this using the 2nd code segment below, but I'm getting a compile error: "The method startActivity(Intent, int) is undefined for the type OnClickListenerSelectPresetItem".
How can I invoke the original Activity from my OnClickListener?
public class SelectPresetItemActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_select_preset_item);
if (savedInstanceState == null) {
getFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment()).commit();
}
readRecords();
}
public void readRecords() {
LinearLayout linearLayoutRecords = (LinearLayout) findViewById(R.id.linearLayoutRecords);
linearLayoutRecords.removeAllViews();
List<preset_item> preset_item = new TableControllerPresetItem(this).read();
if (preset_item.size() > 0) {
for (preset_item obj : preset_item) {
long id = obj.id;
String PresetDesc = obj.preset_desc;
int PresetMinutes = obj.preset_minutes;
String textViewContents = PresetDesc + " - "
+ PresetMinutes + " minutes";
TextView textViewItem = new TextView(this);
textViewItem.setPadding(0, 10, 0, 10);
textViewItem.setText(textViewContents);
textViewItem.setTag(Long.toString(id));
textViewItem.setOnClickListener(new OnClickListenerSelectPresetItem());
linearLayoutRecords.addView(textViewItem);
}
}
else {
TextView locationItem = new TextView(this);
locationItem.setPadding(8, 8, 8, 8);
locationItem.setText("No records yet.");
linearLayoutRecords.addView(locationItem);
}
}listener
The method startActivity(Intent, int) is undefined for the type OnClickListenerSelectPresetItem
public class SelectPresetItemActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_select_preset_item);
if (savedInstanceState == null) {
getFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment()).commit();
}
readRecords();
}
public void readRecords() {
LinearLayout linearLayoutRecords = (LinearLayout) findViewById(R.id.linearLayoutRecords);
linearLayoutRecords.removeAllViews();
List<preset_item> preset_item = new TableControllerPresetItem(this).read();
if (preset_item.size() > 0) {
for (preset_item obj : preset_item) {
long id = obj.id;
String PresetDesc = obj.preset_desc;
int PresetMinutes = obj.preset_minutes;
String textViewContents = PresetDesc + " - "
+ PresetMinutes + " minutes";
TextView textViewItem = new TextView(this);
textViewItem.setPadding(0, 10, 0, 10);
textViewItem.setText(textViewContents);
textViewItem.setTag(Long.toString(id));
textViewItem.setOnClickListener(new OnClickListenerSelectPresetItem());
linearLayoutRecords.addView(textViewItem);
}
}
else {
TextView locationItem = new TextView(this);
locationItem.setPadding(8, 8, 8, 8);
locationItem.setText("No records yet.");
linearLayoutRecords.addView(locationItem);
}
}
This is the OnCLickListener code:
public class OnClickListenerSelectPresetItem implements OnClickListener {
public final static String EXTRA_MEAL_ID = "com.ian.mealtimer.MEAL_ID";
#Override
public void onClick(View view) {
Long selectedMealId = Long.valueOf(view.getTag().toString());
Intent myIntent = new Intent(view.getContext(),
MealActivity.class);
long mealId = -1;
myIntent.putExtra(EXTRA_MEAL_ID, selectedMealId);
startActivity(myIntent, 0);
}
}
You should use:
startActivity (Intent intent)
there is a different method which has an integer parameter:
startActivityForResult (Intent intent, int requestCode)
Also a context can start an activity, so you have to get the context. Easily you can get it from your view:
#Override
public void onClick(View view) {
Long selectedMealId = Long.valueOf(view.getTag().toString());
Intent myIntent = new Intent(view.getContext(),
MealActivity.class);
long mealId = -1;
myIntent.putExtra(EXTRA_MEAL_ID, selectedMealId);
view.getContext().startActivity(myIntent);
}
You can read more about starting activities here.
startActivity is a method of the class Context. The OnClickListener cannot know on which context it should be called. Pass the Context as Parameter to the constructor of the OnClickListener and save it inside:
In class OnClickListenerSelectPresetItem:
private Context context;
public OnClickListenerSelectPresetItem(Context context){
this.context=context;
}
Then call startActivity on this context
this.context.startActivity(myIntent, 0);
And construct them by passing the activity
textViewItem.setOnClickListener(new OnClickListenerSelectPresetItem(this));
How about you pass the activity to the constructor of the OnClickListenerSelectPresetItem
and then use it like the following :
public class OnClickListenerSelectPresetItem implements OnClickListener {
public final static String EXTRA_MEAL_ID = "com.ian.mealtimer.MEAL_ID";
private SelectPresetItemActivity selectPresetItemActivity;
public OnClickListenerSelectPresetItem(SelectPresetItemActivity selectPresetItemActivity){
this.selectPresetItemActivity = selectPresetItemActivity;
}
#Override
public void onClick(View view) {
Long selectedMealId = Long.valueOf(view.getTag().toString());
Intent myIntent = new Intent(view.getContext(),
MealActivity.class);
long mealId = -1;
myIntent.putExtra(EXTRA_MEAL_ID, selectedMealId);
selectPresetItemActivity.startActivity(myIntent, 0);
}
}

Categories

Resources