Static reference to non-static Method

  • Antworten:19
  • OffenNicht stickyNicht beantwortet
  • Forum-Beiträge: 62

17.07.2014, 12:31:38 via Website

Hallo Leute,

ich sitze gerade an einem eigentlich recht Grundlegenden Problem. Und zwar möchte ich eine Imageview die sich in einem Fragment befindet (für Tabs) mit einem Bild aus dem Dateisystem füttern. Ich habe die relevante Codestelle mit "!" markiert:

public static class PlaceholderFragment extends Fragment {

    MeineProfileinstellungenDataModel DataModel;
    static MeineProfileinstellungenDatasource datasource;


    private static final String ARG_SECTION_NUMBER = "section_number";

    public static PlaceholderFragment newInstance(int sectionNumber) {
        PlaceholderFragment fragment = new PlaceholderFragment();
        Bundle args = new Bundle();
        args.putInt(ARG_SECTION_NUMBER, sectionNumber);
        fragment.setArguments(args);
        return fragment;
    }

    public PlaceholderFragment() {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        switch (getArguments().getInt(ARG_SECTION_NUMBER)){
        case 1: View rootView = inflater.inflate(R.layout.fragment_main, container,
                false);

                datasource = new MeineProfileinstellungenDatasource(getActivity());
                datasource.open();
                DataModel = datasource.getProfileinstellungen();

                TextView NameAnzeigen = (TextView) rootView.findViewById(R.id.tvNameAnzeigen);
                NameAnzeigen.setText(DataModel.getName());

                TextView GeburtstagAnzeigen = (TextView) rootView.findViewById(R.id.tvGeburtstagAnzeigen);
                GeburtstagAnzeigen.setText(new StringBuilder()
                // Month is 0 based, just add 1
                .append(DataModel.getTag()).append("-").append(DataModel.getMonat() + 1).append("-")
                .append(DataModel.getJahr()).append(" "));

                datasource.close();

                ImageView Profilbild = (ImageView) rootView.findViewById(R.id.imageViewProfilbild);
                Profilbild.setImageBitmap(getBitmap()); //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

        return rootView;
        case 2: View rootView2 = inflater.inflate(R.layout.fragment_main2, container,
                false);

        return rootView2;
        case 3: View rootView3 = inflater.inflate(R.layout.fragment_main3, container,
                false);

        return rootView3;
        default: return null;}
    }
}

Das ganze ist eine innere Klasse. Hier noch die getBitmap-Methode:

private Bitmap getBitmap() {
    FileInputStream in = null;
    try {
        in = openFileInput("Profilbild.png");
    } catch (FileNotFoundException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }
    Bitmap btm = BitmapFactory.decodeStream(in);
    try {
        in.close();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

     return btm;

}

Das Problem ist, dass er bei der getBitmap Methode entweder sagt cannot make a static reference to a non-static method, und wenn ich dann getBitmap auf static setze, dann sagt er das gleiche für die openFileInput Methode.
Ich weiß, dass es daran liegt, das die Klasse PlaceholderFragment static ist, aber mir fällt keine lösung ein.
Ich hoffe ihr könnt mir weiterhelfen :?

mfg Luca

Antworten
  • Forum-Beiträge: 8.183

17.07.2014, 13:05:31 via Website

Oops....nee, habe Unfug geschrieben :$

— geändert am 17.07.2014, 13:07:32

if all else fails, read the instructions.

Antworten
  • Forum-Beiträge: 11.135

17.07.2014, 13:28:01 via App

Als anfänger nie mit statischen objekten speieln.
Wie mann sieht endet es böse :(
Spass bei seite..
Entferne mal das static Element deiner inner Fragmentklasse. das sollte helfen. Du kannst aus einer statischen klasse keine referenz auf eine nichtstatische machen ohne Vorher ein neues Objekt angelegt zu haben.

LG Pascal //It's not a bug, it's a feature. :) ;)

Antworten
  • Forum-Beiträge: 62

17.07.2014, 14:21:08 via Website

Ne, das static einfach zu entfernen geht nicht, dann funktioniert es vorne und hinten nicht mehr^^

Es muss doch irgendeine eine Lösung geben :?

Antworten
  • Forum-Beiträge: 11.135

17.07.2014, 14:23:06 via Website

Poste mal deinen kompletten Code, dann kann ich nochmal drüberschauen.

LG Pascal //It's not a bug, it's a feature. :) ;)

Antworten
  • Forum-Beiträge: 62

17.07.2014, 14:41:08 via Website

Ok, danke schonmal für deine Mühe.
Achso, die Tabs waren übrigens eine Vorlage von Eclipse, da habe ich nur noch kleine Änderungen vorgenommen

import java.io.FileInputStream;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Locale;

import com.example.stoos.data.MeineProfileinstellungenDataModel;
import com.example.stoos.data.MeineProfileinstellungenDatasource;

import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.ActionBar;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.app.FragmentPagerAdapter;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

public class MainActivity extends ActionBarActivity implements
ActionBar.TabListener {

/**
 * The {@link android.support.v4.view.PagerAdapter} that will provide
 * fragments for each of the sections. We use a {@link FragmentPagerAdapter}
 * derivative, which will keep every loaded fragment in memory. If this
 * becomes too memory intensive, it may be best to switch to a
 * {@link android.support.v4.app.FragmentStatePagerAdapter}.
 */
SectionsPagerAdapter mSectionsPagerAdapter;

/**
 * The {@link ViewPager} that will host the section contents.
 */
ViewPager mViewPager;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // Set up the action bar.
    final ActionBar actionBar = getSupportActionBar();
    actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

    // Create the adapter that will return a fragment for each of the three
    // primary sections of the activity.
    mSectionsPagerAdapter = new SectionsPagerAdapter(
            getSupportFragmentManager());

    // Set up the ViewPager with the sections adapter.
    mViewPager = (ViewPager) findViewById(R.id.pager);
    mViewPager.setAdapter(mSectionsPagerAdapter);

    // When swiping between different sections, select the corresponding
    // tab. We can also use ActionBar.Tab#select() to do this if we have
    // a reference to the Tab.
    mViewPager
            .setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
                @Override
                public void onPageSelected(int position) {
                    actionBar.setSelectedNavigationItem(position);
                }
            });

    // For each of the sections in the app, add a tab to the action bar.
    for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
        // Create a tab with text corresponding to the page title defined by
        // the adapter. Also specify this Activity object, which implements
        // the TabListener interface, as the callback (listener) for when
        // this tab is selected.
        actionBar.addTab(actionBar.newTab()
                .setText(mSectionsPagerAdapter.getPageTitle(i))
                .setTabListener(this));
    }
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {

    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();
    if (id == R.id.action_settings) {
        return true;
    }
    return super.onOptionsItemSelected(item);
}

@Override
public void onTabSelected(ActionBar.Tab tab,
        FragmentTransaction fragmentTransaction) {
    // When the given tab is selected, switch to the corresponding page in
    // the ViewPager.
    mViewPager.setCurrentItem(tab.getPosition());
}

@Override
public void onTabUnselected(ActionBar.Tab tab,
        FragmentTransaction fragmentTransaction) {
}

@Override
public void onTabReselected(ActionBar.Tab tab,
        FragmentTransaction fragmentTransaction) {
}

/**
 * A {@link FragmentPagerAdapter} that returns a fragment corresponding to
 * one of the sections/tabs/pages.
 */
public class SectionsPagerAdapter extends FragmentPagerAdapter {

    public SectionsPagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int position) {
        // getItem is called to instantiate the fragment for the given page.
        // Return a PlaceholderFragment (defined as a static inner class
        // below).
        return PlaceholderFragment.newInstance(position + 1);
    }

    @Override
    public int getCount() {
        // Show 3 total pages.
        return 3;
    }

    @Override
    public CharSequence getPageTitle(int position) {
        Locale l = Locale.getDefault();
        switch (position) {
        case 0:
            return getString(R.string.title_section1).toUpperCase(l);
        case 1:
            return getString(R.string.title_section2).toUpperCase(l);
        case 2:
            return getString(R.string.title_section3).toUpperCase(l);
        }
        return null;
    }
}

/**
 * A placeholder fragment containing a simple view.
 */
public static class PlaceholderFragment extends Fragment {

    MeineProfileinstellungenDataModel DataModel;
    static MeineProfileinstellungenDatasource datasource;


    /**
     * The fragment argument representing the section number for this
     * fragment.
     */
    private static final String ARG_SECTION_NUMBER = "section_number";

    /**
     * Returns a new instance of this fragment for the given section number.
     */
    public static PlaceholderFragment newInstance(int sectionNumber) {
        PlaceholderFragment fragment = new PlaceholderFragment();
        Bundle args = new Bundle();
        args.putInt(ARG_SECTION_NUMBER, sectionNumber);
        fragment.setArguments(args);
        return fragment;
    }

    public PlaceholderFragment() {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        switch (getArguments().getInt(ARG_SECTION_NUMBER)){
        case 1: View rootView = inflater.inflate(R.layout.fragment_main, container,
                false);

                datasource = new MeineProfileinstellungenDatasource(getActivity());
                datasource.open();
                DataModel = datasource.getProfileinstellungen();

                TextView NameAnzeigen = (TextView) rootView.findViewById(R.id.tvNameAnzeigen);
                NameAnzeigen.setText(DataModel.getName());

                TextView GeburtstagAnzeigen = (TextView) rootView.findViewById(R.id.tvGeburtstagAnzeigen);
                GeburtstagAnzeigen.setText(new StringBuilder()
                // Month is 0 based, just add 1
                .append(DataModel.getTag()).append("-").append(DataModel.getMonat() + 1).append("-")
                .append(DataModel.getJahr()).append(" "));

                datasource.close();


                ImageView Profilbild = (ImageView) rootView.findViewById(R.id.imageViewProfilbild);
                //Profilbild.setImageBitmap(getBitmap());

        return rootView;
        case 2: View rootView2 = inflater.inflate(R.layout.fragment_main2, container,
                false);

        return rootView2;
        case 3: View rootView3 = inflater.inflate(R.layout.fragment_main3, container,
                false);

        return rootView3;
        default: return null;}
    }
    private Bitmap getBitmap() {
        FileInputStream in = null;
        try {
            in = openFileInput("Profilbild.png");
        } catch (FileNotFoundException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        Bitmap btm = BitmapFactory.decodeStream(in);
        try {
            in.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

         return btm;

    }

}

Antworten
  • Forum-Beiträge: 11.135

17.07.2014, 14:51:51 via Website

ich würde die PlaceholderFragment in eine eigene Datei auslagern
Ist übersichtlicher.
Zudem sollte dann das static der Klasse weg, was kommen denn dann für Fehler, wenn dies Fehlt?
Alternative:
Klasse Tolls erstellen und Methode dort rein.

LG Pascal //It's not a bug, it's a feature. :) ;)

Antworten
  • Forum-Beiträge: 62

17.07.2014, 17:27:57 via Website

Naja, wenn das static bei der Klasse fehlt, dann will die Methode newInstance() ,dass man entweder ihre static auch wegnimmt oder das static der Klasse wieder einfügt, und wenn man das static von newInstance() weg nimmt, dann funktioniert die getItem Methode nicht mehr, bei der man PlaceholderFragment.newInstance(position + 1) als return Statemant zurück geben lässt, um eine Fragment Isnstanz zu bekommen
Ich habe auch schon versucht das mit einem eigenen Konstruktor zu machen, aber dann sagt Eclipse, man solle doch bitte in Fragments nur defeault Constructors verwenden -.-

Antworten
  • Forum-Beiträge: 11.135

17.07.2014, 17:44:36 via Website

Für was brauchstk
du die newInstance Methode überhaupt?
Dafür gibt es in oop Konstruktoren, denen du deine ID übergibst und dann das Fragment Objekt zurückgibt.
Die new Instance Methode muss in den Konstrukor, anders macht es doch keinen Sinn?
Oder was hast du dir dabei gedacht?

LG Pascal //It's not a bug, it's a feature. :) ;)

Antworten
  • Forum-Beiträge: 62

17.07.2014, 18:00:01 via Website

Wie gesagt, die Tabs sind ne Vorlage von Eclipse, da habe ich mir nich so viel bei gedacht^^
Aber statt newInstance() einfach einen eigenen Konstruktior zu schreiben habe ich schon probiert, wie gesagt, da meckert Eclipse rum, dass man in Fragments nur defeault Konstruktoren verwenden darf -.-

Antworten
  • Forum-Beiträge: 62

17.07.2014, 18:53:26 via Website

Ok, ich habe das Problem gelöst.
Für die die es interessiert :
Diesen

 ImageView Profilbild = (ImageView) rootView.findViewById(R.id.imageViewProfilbild); 

                FileInputStream in = null;
                try {
                    in = rootView.getContext().openFileInput("Profilbild.png");
                    Bitmap btm = BitmapFactory.decodeStream(in);
                    in.close();
                    Profilbild.setImageBitmap(btm);
                } catch (IOException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }

        return rootView;

Codeschnipsel in die onCreateView Methode rein, also inbesondere das rootView.getContext() vorm openFileInput ist wichtig (cool)

Antworten
  • Forum-Beiträge: 11.135

17.07.2014, 19:49:41 via Website

Das hottest du jederzeit so machen können.
Das Problem wird sein, wenn du das gleiche an einer anderen Stelle brauchst.
Da ist eine Methode einfacher.

LG Pascal //It's not a bug, it's a feature. :) ;)

Antworten
  • Forum-Beiträge: 62

17.07.2014, 20:11:41 via Website

Wieso, was für Probleme können denn dann auftreten?

Antworten
  • Forum-Beiträge: 235

18.07.2014, 00:40:28 via Website

Hallo,
@Luca T.
Eclipse implementiert die statische PlaceholderFragment
Klase (angeblich!) wenn man Action bar der Version 7 benutzt.
Ich lerne Android auch aus Euren Forumsbeiträgen ...
Hinweis:
Deine case-Klausel besitzt keine break Anweisungen!
Das ist einfach "Tötlich"
Warum?
Wird zutreffenden Sprungmarke 1 erfühlt: (case 1:) <- zum Thema Escapen ...
getArguments().getInt(ARG_SECTION_NUMBER) == 1

wird ohne break; AUCH! case 2: ... bis zu default:
ausgeführt
Und default, besitzt als Rückgabe -> null
Irgend wann bekommst Du ne NPE und der Pascal wird wieder "Haufen Arbeit bekommen" - :)
Bitte unbedingt! ändern.
und was:

Wieso, was für Probleme können denn dann auftreten?

betrifft, höre auf den Pascal und mache von ne Methode. (sicher ist ... flexibel)

LG
Georg

— geändert am 18.07.2014, 00:43:31

Sorry für Gramatik & Stilistik Fehler.

Antworten
  • Forum-Beiträge: 62

18.07.2014, 01:32:02 via Website

Nein, ein eine Methode bricht bei einem return Statement sofort ab, der Code dahinter wird nicht ausgeführt, dass gilt auch für switch-case Anweisungen (du solltest auch eine Fehlermeldung bekommen wenn du versuchst ein break einzubauen)

Ja, ich habs jetzt einfach in eine Methode gepackt.

Antworten
  • Forum-Beiträge: 235

18.07.2014, 03:21:51 via Website

ich meine das hier:

  ...
  switch (getArguments().getInt(ARG_SECTION_NUMBER)){
        case 1: View rootView = inflater.inflate(R.layout.fragment_main, container,
                false);

                datasource = new MeineProfileinstellungenDatasource(getActivity());
                datasource.open();
                DataModel = datasource.getProfileinstellungen();

                TextView NameAnzeigen = (TextView) rootView.findViewById(R.id.tvNameAnzeigen);
                NameAnzeigen.setText(DataModel.getName());

                TextView GeburtstagAnzeigen = (TextView) rootView.findViewById(R.id.tvGeburtstagAnzeigen);
                GeburtstagAnzeigen.setText(new StringBuilder()
                // Month is 0 based, just add 1
                .append(DataModel.getTag()).append("-").append(DataModel.getMonat() + 1).append("-")
                .append(DataModel.getJahr()).append(" "));

                datasource.close();


                ImageView Profilbild = (ImageView) rootView.findViewById(R.id.imageViewProfilbild);
                //Profilbild.setImageBitmap(getBitmap());

        return rootView;
        case 2: View rootView2 = inflater.inflate(R.layout.fragment_main2, container,
                false);

        return rootView2;
        case 3: View rootView3 = inflater.inflate(R.layout.fragment_main3, container,
                false);

        return rootView3;
        default: return null;}
       ...

Von mir aus, kannst Du machen / glauben .. was Du willst.
Mein Tipp / Vorschlag ist NUR:
die breaks setzten.

Gruß
Georg

Ps.
ich bin raus!

Sorry für Gramatik & Stilistik Fehler.

Antworten
  • Forum-Beiträge: 11.135

18.07.2014, 07:23:13 via App

@Gerog: Ich finde es gut wie du hier mit großem einsatz versuchst zu helfan.
Aber ich finde du gibst zu schnell nach.
Trotzdem Weiter so

LG Pascal //It's not a bug, it's a feature. :) ;)

Antworten
  • Forum-Beiträge: 3.112

18.07.2014, 08:08:14 via App

Das könnte man schöner schreiben, aber ein break hinter einem return ist tatsächlich ein nicht erreichbarer Code.

Antworten
  • Forum-Beiträge: 62

18.07.2014, 11:09:15 via Website

Ja, das hätte ich wohl wirklcih schöner schreiben können, sorry

Aber noch eine Frage, was meinst du denn mit Actionbar Version 7, ich wusste ehrlich gesagt garnicht, dass es da unteschiedliche Versionen gibt ?
(Bzw. , dass man sie mit seinem Code beeinflussen kann)

Antworten
  • Forum-Beiträge: 235

18.07.2014, 23:59:34 via Website

Hallo,
wen ich ein Switch-Case Block / Anweisung OHNE! break´s sehe, leuchtet bei mir ne rote Lampe, und gerade die (Rotelampe) hat mich "geblendet" - habe die returns nicht war genommen, genauer gesagt denen Auswirkung! nicht war genommen. .... habe erste mall solche "innovative Lösung" gesehen ....
UPSS - Entschuldigung!
Was die Version 7 und Actionbar betrifft, lese bitte selber (habe mich falsch ausgedrückt)
Link

@Pascal P.

Aber ich finde du gibst zu schnell nach.

???

Trotzdem Weiter so

THIA,
ich werde sagen; -> ich ziehe mich mit dem Helfen hier lieber ins Hintergrund.
Main "Brain" - will langsam nicht so wie ich es gewöhnt bin - (silly)

LG
Georg

— geändert am 19.07.2014, 00:00:42

Sorry für Gramatik & Stilistik Fehler.

Antworten