Georgi Koemdzhiev
Georgi Koemdzhiev

Reputation: 11931

Call fragment method in an activity?

I am trying to call a fragment method from an activity but it causes a OutOfMemoryError. I was following this tutorial Link

Error reporting crash
                                                                   java.lang.OutOfMemoryError: Failed to allocate a 6289456 byte allocation with 4315368 free bytes and 4MB until OOM
                                                                       at java.lang.AbstractStringBuilder.enlargeBuffer(AbstractStringBuilder.java:95)
                                                                       at java.lang.AbstractStringBuilder.append0(AbstractStringBuilder.java:125)
                                                                       at java.lang.StringBuffer.append(StringBuffer.java:278)
                                                                       at java.io.StringWriter.write(StringWriter.java:123)
                                                                       at com.android.internal.util.FastPrintWriter.flushLocked(FastPrintWriter.java:358)
                                                                       at com.android.internal.util.FastPrintWriter.appendLocked(FastPrintWriter.java:303)
                                                                       at com.android.internal.util.FastPrintWriter.write(FastPrintWriter.java:625)
                                                                       at com.android.internal.util.FastPrintWriter.append(FastPrintWriter.java:658)
                                                                       at java.io.PrintWriter.append(PrintWriter.java:691)
                                                                       at java.io.PrintWriter.append(PrintWriter.java:687)
                                                                       at java.io.Writer.append(Writer.java:198)
                                                                       at java.lang.Throwable.printStackTrace(Throwable.java:324)
                                                                       at java.lang.Throwable.printStackTrace(Throwable.java:300)
                                                                       at android.util.Log.getStackTraceString(Log.java:343)
                                                                       at com.android.internal.os.RuntimeInit.Clog_e(RuntimeInit.java:61)
                                                                       at com.android.internal.os.RuntimeInit.-wrap0(RuntimeInit.java)
                                                                       at com.android.internal.os.RuntimeInit$UncaughtHandler.uncaughtException(RuntimeInit.java:86)
                                                                       at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:693)
                                                                       at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:690)

Render problems in the fragment xml: enter image description here

This is my fragment xml: [current_forefast_fragment]

<RelativeLayout 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"
            android:background="@drawable/bg_gradient">

<fragment
    android:id="@+id/current_fragment"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:name="koemdzhiev.com.stormy.Current_forecast_fragment"/>

<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/iconImageView"
    android:src="@mipmap/clear_night"
    android:adjustViewBounds="true"
    android:scaleType="fitXY"
    android:contentDescription="@string/weatherIconDesc"
    android:layout_above="@+id/locationLabel"
    android:layout_marginBottom="20dp"
    android:layout_centerHorizontal="true"/>
<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="requesting current location..."
    android:id="@+id/locationLabel"
    android:textColor="@android:color/white"
    android:textSize="22sp"
    android:layout_above="@+id/timeLabel"
    android:layout_centerHorizontal="true"
    android:layout_marginBottom="51dp"/>

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="--"
    android:id="@+id/temperatureLabel"
    android:layout_centerVertical="true"
    android:layout_centerHorizontal="true"
    android:textColor="@android:color/white"
    android:textSize="125sp"/>

<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/degreeImageView"
    android:layout_alignTop="@+id/temperatureLabel"
    android:layout_toRightOf="@+id/temperatureLabel"
    android:layout_toEndOf="@+id/temperatureLabel"
    android:src="@mipmap/degree"
    android:layout_marginTop="27dp"
    android:layout_marginLeft="10dp"/>

</RelativeLayout>

This is my fragment code:

public class Current_forecast_fragment extends Fragment {
private MainActivity mActivity;
@InjectView(R.id.timeLabel)
TextView mTimeLabel;
@InjectView(R.id.temperatureLabel)
TextView mTemperatureLabel;
@InjectView(R.id.humidityValue)
TextView mHumidityValue;
@InjectView(R.id.precipValue)
TextView mPrecipValue;
@InjectView(R.id.summaryLabel)
TextView mSummaryLabel;
@InjectView(R.id.locationLabel)
TextView mLocationLabel;
@InjectView(R.id.windSpeedValue)
TextView mWindSpeedValue;
@InjectView(R.id.iconImageView)
ImageView mIconImageView;
@InjectView(R.id.refreshImageView)
ImageView mRefreshImaveView;
@InjectView(R.id.progressBar)
ProgressBar mProgressBar;
@InjectView(R.id.degreeImageView)
ImageView mDegreeImageView;

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    mActivity = ((MainActivity) getActivity());
}

@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.current_forefast_fragment, container, false);
    ButterKnife.inject(this, v);


    return v;
}


public void toggleRefresh() {
    if (mProgressBar.getVisibility() == View.INVISIBLE) {
        mProgressBar.setVisibility(View.VISIBLE);
        mRefreshImaveView.setVisibility(View.INVISIBLE);
    } else {
        mProgressBar.setVisibility(View.INVISIBLE);
        mRefreshImaveView.setVisibility(View.VISIBLE);
    }

    // updates the dysplay with the data in the CUrrentWeather locaal object

}

public void updateDisplay() {
    Current current = mActivity.mForecast.getCurrent();
    //setting the current weather details to the ui
    mTemperatureLabel.setText(current.getTemperature() + "");
    mTimeLabel.setText("At " + current.getFormattedTime() + " it will be");
    mHumidityValue.setText(current.getHumidity() + "%");
    mPrecipValue.setText(current.getPrecipChange() + "%");
    mSummaryLabel.setText(current.getSummery());
    mWindSpeedValue.setText(current.getWindSpeed() + "");
    mLocationLabel.setText(current.getTimeZone());
    mActivity.getLocationName();
    Drawable drawable = ContextCompat.getDrawable(mActivity, current.getIconId());
    mIconImageView.setImageDrawable(drawable);

}

}

And this is the code in main activity that causes the null pointer exception. This happens when I try to cast the fragment to Current_forecast_fragment:

public class MainActivity extends AppCompatActivity {
ViewPager pager;
ViewPagerAdapter adapter;
SlidingTabLayout tabs;
CharSequence Titles[]={"Current","Hourly","Daily"};
int Numboftabs =3;
Current_forecast_fragment mCurrent_forecast_fragment;

public static final String TAG = MainActivity.class.getSimpleName();
public static final String LOCATION_KEY = "location_key";
public Forecast mForecast;
public static final String DAILY_FORECAST = "DAILY_FORECAST";
public static final String HOURLY_FORECAST = "HOURLY_FORECAST";
//default coordinates - Gotse Delchev, UK Lati:57.156866 ; Long:
private double latitude = 41.5667;
private double longitude = 23.7333;
private LocationManager locationManager;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    //-----------MY CODE STARTS HERE-----------------

    mCurrent_forecast_fragment = (Current_forecast_fragment) getSupportFragmentManager().findFragmentById(R.id.current_fragment);
    //Log.d("MainActivity",mCurrent_forecast_fragment.getTag() + "Georgi");
    getLocation();

    // Creating The ViewPagerAdapter and Passing Fragment Manager, Titles fot the Tabs and Number Of Tabs.
    adapter =  new ViewPagerAdapter(getSupportFragmentManager(),Titles,Numboftabs);

    // Assigning ViewPager View and setting the adapter
    pager = (ViewPager) findViewById(R.id.pager);
    pager.setAdapter(adapter);

    // Assiging the Sliding Tab Layout View
    tabs = (SlidingTabLayout) findViewById(R.id.tabs);
    tabs.setDistributeEvenly(true); // To make the Tabs Fixed set this true, This makes the tabs Space Evenly in Available width

    // Setting Custom Color for the Scroll bar indicator of the Tab View
    tabs.setCustomTabColorizer(new SlidingTabLayout.TabColorizer() {
        @Override
        public int getIndicatorColor(int position) {
            return getResources().getColor(R.color.tabsScrollColor);
        }
    });

    // Setting the ViewPager For the SlidingTabsLayout
    tabs.setViewPager(pager);




}

Any suggestions?

Upvotes: 2

Views: 2611

Answers (1)

flyingAssistant
flyingAssistant

Reputation: 920

You have placed fragment layout inside a fragment current_forefast_fragment.xml. This has caused looped impact in your Current_forecast_fragment and OutOfMemoryError. So, delete this line from current_forefast_fragment.xml:

<fragment
    android:id="@+id/current_fragment"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:name="koemdzhiev.com.stormy.Current_forecast_fragment"/>

In order to get a fragment reference you will need modify your MainActivity and other fragment classes from where you want retain Current_forecast_fragment. I'll assume that you have two fragments Tab1.java and Current_forecast_fragment.java. In first one we need to define Callback interface with proper method:

import android.app.Activity;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;

/**
 * Created by hp1 on 21-01-2015.
 */
public class Tab1 extends Fragment {

    private Callback callback;

    public interface Callback{
        Current_forecast_fragment getCurrentForecastFragment();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View v =inflater.inflate(R.layout.tab_1,container,false);

        Button btn1 = (Button) v.findViewById(R.id.btn1);
        btn1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                callback.getCurrentForecastFragment();
            }
        });
        return v;
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        callback = (Callback) activity;
    }
}

After that implement mentioned Callback in class MainActivity:

public class MainActivity extends AppCompatActivity implements Tab1.Callback {
    ViewPager pager;
    ViewPagerAdapter adapter;
    SlidingTabLayout tabs;
    CharSequence Titles[] = {"Current", "Hourly", "Daily"};
    int Numboftabs = 3;
    Current_forecast_fragment mCurrent_forecast_fragment;

    public static final String TAG = MainActivity.class.getSimpleName();
    public static final String LOCATION_KEY = "location_key";
    public static final String DAILY_FORECAST = "DAILY_FORECAST";
    public static final String HOURLY_FORECAST = "HOURLY_FORECAST";
    //default coordinates - Gotse Delchev, UK Lati:57.156866 ; Long:
    private double latitude = 41.5667;
    private double longitude = 23.7333;
    private LocationManager locationManager;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //-----------MY CODE STARTS HERE-----------------

        //mCurrent_forecast_fragment = (Current_forecast_fragment) getSupportFragmentManager().findFragmentById(R.id.current_fragment);
        //Log.d("MainActivity",mCurrent_forecast_fragment.getTag() + "Georgi");
        //getLocation();

        // Creating The ViewPagerAdapter and Passing Fragment Manager, Titles fot the Tabs and Number Of Tabs.
        adapter = new ViewPagerAdapter(getSupportFragmentManager(), Titles, Numboftabs);

        // Assigning ViewPager View and setting the adapter
        pager = (ViewPager) findViewById(R.id.pager);
        pager.setAdapter(adapter);

        // Assiging the Sliding Tab Layout View
        tabs = (SlidingTabLayout) findViewById(R.id.tabs);
        tabs.setDistributeEvenly(true); // To make the Tabs Fixed set this true, This makes the tabs Space Evenly in Available width

        // Setting Custom Color for the Scroll bar indicator of the Tab View
        tabs.setCustomTabColorizer(new SlidingTabLayout.TabColorizer() {
            @Override
            public int getIndicatorColor(int position) {
                return getResources().getColor(R.color.tabsScrollColor);
            }
        });

        // Setting the ViewPager For the SlidingTabsLayout
        tabs.setViewPager(pager);


    }

    public Current_forecast_fragment getCurrentForecastFragment() {
        // second argument is position of Current_forecast_fragment in ViewPagerAdapter
        mCurrent_forecast_fragment = (Current_forecast_fragment) adapter.instantiateItem(pager, 1);
        return mCurrent_forecast_fragment;
    }
}

Now you can access your Current_forecast_fragment instance from Tab1.java by calling interface method callback.getCurrentForecastFragment().

Upvotes: 1

Related Questions