2016-02-29 13 views
9

मैं नोटिस गूगल प्ले स्टोर से अन्य पहेली क्षुधा के रूप में कई के रूप में 400 अलग चल पहेली टुकड़ेमैं स्मृति से बाहर किए बिना droid में एक पहेली ऐप कैसे बना सकता हूं?

मैं जानने के लिए कैसे कम से कम एक छवि है कि मेरी पहेली का प्रतिनिधित्व करेंगी लेने की कोशिश कर दिया गया है, फसल तक जा सकता है कि कुछ अनुभाग और छवि पहेली को मास्क करें जो मेरे व्यक्तिगत पहेली टुकड़े बनाने के लिए एक पहेली टुकड़ा डिजाइन के साथ छोड़ा गया है

मैं अपने ऐप के लिए 20 टुकड़ों के साथ अधिकतम करना चाहता हूं लेकिन अब तक मेरे एंड्रॉइड स्टूडियो मेमोरी लॉग के अनुसार बिटमैप कारखाना एक पहेली टुकड़ा बना रहा है जिसे मैं 18 एमबी मेमोरी का उपयोग कर रहा हूं, ऐप के सभी अन्य कार्यों के साथ 20 टुकड़े बनाए गए हैं, मैं 400 + एमबी मेमोरी का उपयोग कर रहा हूं जिसे मुझे "bigHeap = tru" ई "स्मृति से बाहर निकलने के लिए, लेकिन मैं उन उच्च सीमाओं से अधिक होने के करीब हूं कि ऐप सुपर सुस्त है और पर्याप्त एनिमेटेड गतिविधि अनिवार्य रूप से ऐप को क्रैश कर देगी

मुझे यह जानना अच्छा लगेगा कि उन अन्य Play store पहेली क्षुधा कर रहे हैं कि मैं

नहीं कर रहा हूँ किसी भी इनपुट बहुत

सराहना की FYI करें मैं अपनी छवियों के लिए PNG24 उपयोग कर रहा हूँ और अपने परीक्षण छवि पर आयाम 556x720

है यहाँ एक उदाहरण है कि अगर मैं केवल एक एनिमेटेड-सक्षम पहेली टुकड़ा छवि बनाने के लिए थे

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    this.requestWindowFeature(Window.FEATURE_NO_TITLE);//Remove title bar 
    this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);//Hides notification bar 
    this.setContentView(R.layout.activity_main);//set content view AFTER ABOVE sequence (to avoid crash) 

    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); 

    mainDisplay = getWindowManager().getDefaultDisplay(); 
    mainLayout = (ViewGroup) findViewById(R.id.id_layout); 

    DisplayMetrics m = new DisplayMetrics(); 
    this.getWindowManager().getDefaultDisplay().getMetrics(m); 
    int windowHeight = m.heightPixels; 
    int windowWidth = m.widthPixels; 

    offsetX = (windowWidth/1440.0f); 
    offsetY = (windowHeight/2560.0f); 

    ourContext = this; 

    xpos = new float[2]; 
    ypos = new float[2]; 

    iv_PuzzleOne(); 

    bkgdbm = BitmapFactory.decodeResource(getResources(), R.drawable.puzzleimage); 

    paintObject = new Paint(); 
    paintObject.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.XOR)); 

    bm_PuzzleOne(); 

    thisTimerTask = new ThisClass(); 
    thisTimer = new Timer(); 
    thisTimer.scheduleAtFixedRate(thisTimerTask, 16, 16); 

    touchpad = new ImageButton(this); 
    SetPos(0, 0, 1440, 2560); 
    touchpad.setLayoutParams(layoutPositioner); 
    touchpad.getBackground().setAlpha(1); 
    mainLayout.addView(touchpad); 

    touchpad.setOnTouchListener(new View.OnTouchListener() { 

     //@SuppressLint("NewApi") 
     @Override 
     public boolean onTouch(View v, MotionEvent event) { 

      if (event.getAction() == MotionEvent.ACTION_DOWN) { 
       xpos[0] = event.getX(); //storing my finger's position coordinates when I first touch the screen into the 1st element 
       ypos[0] = event.getY(); 

       if ((event.getX() > imgx1) && (event.getX() < imgx1 + imagewidth1) 
         && (event.getY() > imgy1) && (event.getY() < imgy1 + imageheight1)) { 
        touching1Puzzle = true; 
        img1.bringToFront(); 
       } 

      } 

      if (event.getAction() == MotionEvent.ACTION_MOVE) { 

       xpos[1] = event.getX(); //add my finger's new current coordinates into the 2nd element 
       ypos[1] = event.getY(); 

       if (touching1Puzzle) { 
        adjustImg(); 
       } 
      } 

      if (event.getAction() == MotionEvent.ACTION_UP) { 
       if (touching1Puzzle) { 
        touching1Puzzle = false; 
       } 

      } 

      return false; 
     } 

    }); 
} 


void bm_PuzzleOne() 
{ 
    //start of 1st puzzle 

    foregdimg1 = BitmapFactory.decodeResource(getResources(), R.drawable.puzzlepieceprac);//puzzle cut out (42.48MB) +6.15 
    mutableforegdimg1 = foregdimg1.copy(Bitmap.Config.ARGB_8888, true); //(48.32MB) +5.84 

    compositeImage1 = Bitmap.createBitmap(mutableforegdimg1);//cuts out foreground info into bkgdimage (54.43MB) +6.11 

    imgCanvas1 = new Canvas(compositeImage1); //canvas references puzzle cut out image (54.43MB) +0 
    imgCanvas1.drawBitmap(croppedBmp, null, new Rect(0, 0, 1500, 2000), paintObject);//places puzzle image on canvas (54.43MB) +0 

    img1.setImageBitmap(compositeImage1); 

} 


void iv_PuzzleOne() 
{ 
    img1 = new ImageView(ourContext); 
    SetPos(imgx1, imgy1, imagewidth1, imageheight1); 
    //bkgdimg.setImageResource(R.drawable.c); 
    //img1.setBackgroundColor(0xffF07305); //Orange 
    img1.setLayoutParams(layoutPositioner); 
    mainLayout.addView(img1); 

} 

void adjustImg() 
{ 
    if (touching1Puzzle) 
    { 
     if (xpos[1] > xpos[0]) //if the image had slid to the right 
     { 
      xPositionDifference = xpos[1] - xpos[0]; // find the difference in coordinate value between where my finger was and where it currently is 
      imgx1 += xPositionDifference; //add that difference to the current image position ... 

      xpos[0] += xPositionDifference; // ... store that difference for the next shift in finger postion 

     } else if (xpos[1] < xpos[0]) //if the image had slid to the left 
     { 
      xPositionDifference = xpos[0] - xpos[1]; // find the difference in coordinate value between where my finger was and where it currently is 
      imgx1 -= xPositionDifference; //subtract that difference to the current image position ... 

      xpos[0] -= xPositionDifference; // ... store that difference for the next shift in finger postion 
     } 

     if (ypos[1] > ypos[0]) //if the image had slid to the right 
     { 
      yPositionDifference = ypos[1] - ypos[0]; // find the difference in coordinate value between where my finger was and where it currently is 
      imgy1 += yPositionDifference; //add that difference to the current image position ... 

      ypos[0] += yPositionDifference; // ... store that difference for the next shift in finger postion 

     } else if (ypos[1] < ypos[0]) //if the image had slid to the left 
     { 
      yPositionDifference = ypos[0] - ypos[1]; // find the difference in coordinate value between where my finger was and where it currently is 
      imgy1 -= yPositionDifference; //subtract that difference to the current image position ... 

      ypos[0] -= yPositionDifference; // ... store that difference for the next shift in finger postion 

     } 
    } 

} 

class ThisClass extends TimerTask { 

    @Override 
    public void run() { 
     MainActivity.this.runOnUiThread(new Runnable() { 
      @Override 
      public void run() { 

       if(touching1Puzzle) 
       {SetPos(imgx1, imgy1, imagewidth1, imageheight1); 
        img1.setLayoutParams(layoutPositioner);} 

      } 
     }); 
    } 
} 

public void SetPos(float x, float y, float width, float height) { 
    layoutPositioner = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT); 
    layoutPositioner.topMargin = (int) (offsetY * y); 
    layoutPositioner.leftMargin = (int) (offsetX * x); 
    layoutPositioner.width = (int) (width * offsetX); 
    layoutPositioner.height = (int) (height * offsetY); 
} 

}

यह यह कैसा जब मैं 5 छवियों

http://s15.postimg.org/ymqspk77v/Screenshot_2016_02_29_07_19_26.png

उत्तर

2

आप बस छवियों के बजाय वैक्टर का उपयोग .. आप अनुप्रयोग और भंडारण को चलाने के लिए अधिक स्मृति बचत होगी। यह बहुत अच्छी तरह से समर्थित है। और आप एसवीजी संसाधनों का उपयोग कर सकते हैं

+0

धन्यवाद माहेर, मैंने कभी भी इसके साथ पहले और बाद में वैक्टर का उपयोग नहीं किया था, मैं अकेले उसके साथ स्मृति की नाव लोड को बंद कर रहा हूं, मुझे दर्द होता है कि मेरे पास पर्याप्त नहीं था ब्याज अवधि समाप्त होने से पहले ज़ेडद और स्मार्टज़ के तीसरे पक्ष के सुझावों का परीक्षण करने का समय [मैं अपने खाली समय में 2 नौकरियों और प्रोग्रामिंग को जोड़ रहा हूं] लेकिन ऐसा लगता है कि वे सही दिशा में नेतृत्व के समाधान थे ... जीईडी आपके लिए धन्यवाद गहराई से जवाब यह सिर्फ मेरे विशिष्ट मुद्दे के लिए समाधान नहीं था – user1091368

3

लोड ठीक है आइए देखते हैं दिखता है।

सभी की

सबसे पहले आप ताकि आप उन्हें नीचे पैमाने पर कर सकते हैं, इस बड़े होने के लिए पहेली टुकड़े की जरूरत नहीं है: http://developer.android.com/training/displaying-bitmaps/load-bitmap.html

से

छवि subsample लिए डिकोडर कहता हूं, एक छोटे लोड हो रहा है स्मृति में संस्करण, सेट में नमूना आकार अपने BitmapFactory.Options ऑब्जेक्ट में सच है। उदाहरण के लिए, संकल्प 2048x1536 के साथ एक छवि जिसे 4 में नमूना आकार के साथ डीकोड किया गया है, लगभग 512x384 का बिटमैप उत्पन्न करता है। स्मृति में इस लोड हो रहा है पूर्ण छवि (ARGB_8888 की एक बिटमैप विन्यास संभालने)

दूसरी बात आप ठंड से आवेदन को रोकने के लिए एक AsyncTask में लोड हो रहा है बिटमैप का प्रयास करना चाहिए के लिए 12MB 0.75MB के बजाय का उपयोग करता है। http://developer.android.com/training/displaying-bitmaps/index.html:

तीसरा आप अपने बिटमैप चीजें तेजी लाने के लिए

http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html

private LruCache<String, Bitmap> mMemoryCache; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    ... 
    // Get max available VM memory, exceeding this amount will throw an 
    // OutOfMemory exception. Stored in kilobytes as LruCache takes an 
    // int in its constructor. 
    final int maxMemory = (int) (Runtime.getRuntime().maxMemory()/1024); 

    // Use 1/8th of the available memory for this memory cache. 
    final int cacheSize = maxMemory/8; 

    mMemoryCache = new LruCache<String, Bitmap>(cacheSize) { 
     @Override 
     protected int sizeOf(String key, Bitmap bitmap) { 
      // The cache size will be measured in kilobytes rather than 
      // number of items. 
      return bitmap.getByteCount()/1024; 
     } 
    }; 
    ... 
} 

public void addBitmapToMemoryCache(String key, Bitmap bitmap) { 
    if (getBitmapFromMemCache(key) == null) { 
     mMemoryCache.put(key, bitmap); 
    } 
} 

public Bitmap getBitmapFromMemCache(String key) { 
    return mMemoryCache.get(key); 
} 

पर्याप्त होना चाहिए कि लेकिन मामले में यह यहाँ नहीं है सभी स्रोतों और फिर कुछ अतिरिक्त हैं LruCache का उपयोग कर कैश कर सकते

तुम भी उपयोग करके देख सकते

void bm_PuzzleOne() 
{ 
    //start of 1st puzzle 
    BitmapFactory.Options opt = new BitmapFactory.Options(); 

    //makes a loaded image mutable 
    opt.inMutable=true; 
    //reduces density to that of screen 
    opt.inTargetDensity = this.context.getResources().getDisplayMetrics().densityDpi; 
    opt.inScaled=true; 

    //makes bitmap half as big 
    opt.inSampleSize=2; 

    //foregdimg1 = BitmapFactory.decodeResource(getResources(), R.drawable.puzzlepieceprac);//puzzle cut out (42.48MB) +6.15 
    mutableforegdimg1 = BitmapFactory.decodeResource(getResources(), R.drawable.puzzlepieceprac,opt) 

    compositeImage1 = Bitmap.createBitmap(mutableforegdimg1);//cuts out foreground info into bkgdimage (54.43MB) +6.11 

    imgCanvas1 = new Canvas(compositeImage1); //canvas references puzzle cut out image (54.43MB) +0 
    imgCanvas1.drawBitmap(croppedBmp, null, new Rect(0, 0, 1500, 2000), paintObject);//places puzzle image on canvas (54.43MB) +0 

    img1.setImageBitmap(compositeImage1); 

} 
बजाय

void bm_PuzzleOne() 
{ 
    //start of 1st puzzle 

    foregdimg1 = BitmapFactory.decodeResource(getResources(), R.drawable.puzzlepieceprac);//puzzle cut out (42.48MB) +6.15 
    mutableforegdimg1 = foregdimg1.copy(Bitmap.Config.ARGB_8888, true); //(48.32MB) +5.84 

    compositeImage1 = Bitmap.createBitmap(mutableforegdimg1);//cuts out foreground info into bkgdimage (54.43MB) +6.11 

    imgCanvas1 = new Canvas(compositeImage1); //canvas references puzzle cut out image (54.43MB) +0 
    imgCanvas1.drawBitmap(croppedBmp, null, new Rect(0, 0, 1500, 2000), paintObject);//places puzzle image on canvas (54.43MB) +0 

    img1.setImageBitmap(compositeImage1); 

} 
+0

जब आप कहते हैं कि मुझे उनकी आवश्यकता नहीं है तो मुझे लगता है कि आप 1500x2000 पर तैयार बिटमैप का जिक्र कर रहे हैं ...प्रीलोडेड छवि 1500x2000 नहीं है, मुझे इसे आकार में विस्तारित करने के लिए मजबूर होना पड़ता है केवल मुखौटा पहेली टुकड़ा सही दिखता है ... मेरी पहेली छवि का आकार 425x601 प्रीलोड किया गया है, मुझे पहेली छवि के आकार का विस्तार करने के लिए मजबूर होना पड़ता है इसके लिए मेरे पहेली टुकड़े के आकार में फिट होना ... मुझे उम्मीद है कि यह समझ में आता है और मेरे वर्तमान लटकने के लिए और स्पष्टता जोड़ता है ... यह एक उदाहरण है जो यह दिखता है ... http: //postimg.org/image/o62dgyw0t/ – user1091368

+0

एक संपादन किया, इसे जांचें और मुझे बताएं कि यह काम करता है या नहीं। इसके अलावा, क्या आप इसे compositeImage में जोड़ने के बाद mutableforegdimg का उपयोग करते हैं? यदि आपको इसे रीसायकल करने का प्रयास नहीं करना चाहिए – JeD

1

सब मैं उनकी महान उत्तर के लिए @JeD धन्यवाद करना चाहिए, लेकिन मैं मुझे लगता है कि इस सवाल का जवाब अलग है उल्लेख करना चाहिए पहले।

मूल बातें से शुरू करते ...


प्रत्येक Android डिवाइस एक विशिष्ट "ढेर आकार" है। यह कुछ उपकरणों में 16 एमजी से 64 एमजी और 128 एमजी से भी शुरू होता है! (मुझे 128 मिलीग्राम के बारे में निश्चित नहीं है: डी)

तो जब भी आप अपने दृश्य में drawable का उपयोग करते हैं, तो इसमें विशिष्ट मात्रा में राम होता है।

प्रश्न: इसकी गणना कैसे की जाती है ?!

इसका drawable एस आयाम, आकार नहीं। उदाहरण के लिए हमारे पास 500 केबी आकार के साथ दो drawable एस हैं। उनमें से एक आयाम 500 * 500 है, दूसरे में 700 * 700 है दूसरा दूसरा ढेर लेता है हालांकि दोनों आकार समान थे! सूत्र यह है: WIDTH * HEIGHT * 4 BYTE (4 एआरजीबी से आता है, प्रत्येक डेटा को डेटा स्टोर करने के लिए चार बाइट लेता है)

अब तक, आपको समझना चाहिए कि आप कई छवियों को एक साथ उपयोग नहीं कर सकते हैं! यदि आप LRUCACH का उल्लेख @JeD के रूप में करना चाहते हैं, तो आप अपनी कुछ छवियों को खो देंगे क्योंकि आपका ढेर पूरा हो जाएगा।

प्रश्न: तो हमें क्या करना चाहिए ?!

उत्तर तीसरे पक्ष के इंजन और कैनवास का उपयोग कर रहा है! COCOS2D, BOX2D, आदि जैसे गेम इंजन भी अच्छे उदाहरण हैं या एनडीके का उपयोग करके जो आपके ऐप को मुफ्त में बनाता है !!! : डी

2

मैं ग्लाइड या पिकासो जैसी छवि लोडिंग लाइब्रेरी का उपयोग करने का सुझाव देता हूं, जो आपके लिए भारी भारोत्तोलन को संभालने में मदद करता है।

https://github.com/bumptech/glide

http://square.github.io/picasso/

संबंधित मुद्दे